mudlet/src/TMap.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

3732 lines
151 KiB
C++
Raw Permalink Normal View History

2010-08-25 00:41:43 +02:00
/***************************************************************************
* Copyright (C) 2008-2013 by Heiko Koehn - KoehnHeiko@googlemail.com *
2017-04-16 22:33:35 -07:00
* Copyright (C) 2014-2017 by Ahmed Charles - acharles@outlook.com *
* Copyright (C) 2014-2024, 2026 by Stephen Lyons *
* - slysven@virginmedia.com *
2010-08-25 00:41:43 +02:00
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "TMap.h"
#include "Host.h"
#include "TArea.h"
#include "TConsole.h"
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
#include "TEvent.h"
#include "TMapLabel.h"
#include "TMapViewManager.h"
#include "TRoomDB.h"
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
#include "XMLimport.h"
2017-04-14 00:40:02 -07:00
#include "dlgMapper.h"
#include "TLuaInterpreter.h"
#include "mapInfoContributorManager.h"
Infrastructure: move away from constructor initialisation lists - part 2 (#5937) For classes from "T2*" to "TM*" (approximately)... I have steered away from using `{}` to initialise simple, POD data types in favour of explicitly stating what their default values are. Also: * remove unused `(QColor) TAction::mButtonColor` and it's associated getter and setter. Also remove the save code from the `XMLexport` class and ensure it is skipped and silently discarded in the load code in `XMLimport`. * Make `private` some members of the `TFlipButton` class that probably weren't ever intended to be `public` * Remove unneeded named argument for `lua_State*` type in many (but not all) function declarations in `TLuaInterpreter.h` file - they aren't needed and whether an `L` was present or not seems to entirely down to the whim of the individual coder of each function...! * Rejig some of the initiliasations in the `TLuaInterpreter` class * Refactor a chunk of code n the `TMap` class used to (re)initialise the 16 colours user settable from the preferences dialogue to a method: `(void) TMap::restore16ColorSet()` - so that it can be used in three other places as well as the constuctor. * Remove unused `(int) T2DMap::gzoom`. * Add missing `TMediaData.h` file to qmake project file. Note: `QPointer<T>` instances do NOT need initialisation, they are automagically instantiated with a `nullptr` value. Revised to change code to fit in with PR #6133 There were some pre-Qt 5.14.0 version checks that are no longer relevant. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2022-06-27 20:36:51 +01:00
#include "mudlet.h"
#include <QBuffer>
infrastructure: harden the build for the minimum supported Qt version (#9510) #### Brief overview of PR changes/additions - Include QJson/QtCore headers directly in the 16 files that only reached those types through transitive includes; headers forward-declare where a reference suffices - Pass the MMCP command bytes to QString::arg() as explicit QChar (wire bytes unchanged) #### Motivation for adding to Mudlet An audit comment in #9011 reported that development does not build at the declared Qt 6.8.2 lower bound; building against official Qt 6.8.2 binaries shows it actually builds cleanly today, but only via transitive includes and arg() overload-set details that shift between Qt releases - this PR makes both explicit so the lower bound keeps working. #### Other info (issues closed, discussion etc) Relates to #9011 (not closed by this PR). Verification of the audit's two Qt 6.8.2 claims, done against official Qt 6.8.2 gcc_64 binaries: - Unmodified development configures and builds completely (387/387 targets, all functional tests link) at 6.8.2, so the reported QJson include errors and MMCP arg() compile failures did not reproduce. This branch builds green at 6.8.2 as well. - On the arg() claim specifically: 6.8.2's qstring.h declares `arg(char)` unconditionally, so the two live single-arg sites in MMCPServer.cpp already compiled. The genuinely 6.8.2-problematic pattern - multi-arg `.arg(char, ...)`, which on 6.8.2 resolves to `arg(char a, int fieldWidth)` and would silently eat the second byte as a field width - only occurs in commented-out code (MMCPServer.cpp around lines 534 and 1054). If that code is ever revived, it needs the QChar wrapping. - MMCP byte-equivalence: a small harness compiled against Qt 6.12 shows the old and new forms produce identical toLatin1() frames (0x06 for TextGroup, 0xFF for End). On 6.8.2, `arg(char)` forwards to QLatin1Char - the same Latin-1 mapping `QChar(char)` uses - so frames are byte-identical there too. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-fable-5 **Test case:** - Build against Qt 6.8.x: done for this PR with official 6.8.2 binaries on Linux - full build green on this branch and on unmodified development. - At minimum: the current build stays green (CI covers newer Qt only).
2026-07-26 13:30:15 +02:00
#include <QDataStream>
#include <QElapsedTimer>
#include <QJsonArray>
#include <QJsonDocument>
infrastructure: harden the build for the minimum supported Qt version (#9510) #### Brief overview of PR changes/additions - Include QJson/QtCore headers directly in the 16 files that only reached those types through transitive includes; headers forward-declare where a reference suffices - Pass the MMCP command bytes to QString::arg() as explicit QChar (wire bytes unchanged) #### Motivation for adding to Mudlet An audit comment in #9011 reported that development does not build at the declared Qt 6.8.2 lower bound; building against official Qt 6.8.2 binaries shows it actually builds cleanly today, but only via transitive includes and arg() overload-set details that shift between Qt releases - this PR makes both explicit so the lower bound keeps working. #### Other info (issues closed, discussion etc) Relates to #9011 (not closed by this PR). Verification of the audit's two Qt 6.8.2 claims, done against official Qt 6.8.2 gcc_64 binaries: - Unmodified development configures and builds completely (387/387 targets, all functional tests link) at 6.8.2, so the reported QJson include errors and MMCP arg() compile failures did not reproduce. This branch builds green at 6.8.2 as well. - On the arg() claim specifically: 6.8.2's qstring.h declares `arg(char)` unconditionally, so the two live single-arg sites in MMCPServer.cpp already compiled. The genuinely 6.8.2-problematic pattern - multi-arg `.arg(char, ...)`, which on 6.8.2 resolves to `arg(char a, int fieldWidth)` and would silently eat the second byte as a field width - only occurs in commented-out code (MMCPServer.cpp around lines 534 and 1054). If that code is ever revived, it needs the QChar wrapping. - MMCP byte-equivalence: a small harness compiled against Qt 6.12 shows the old and new forms produce identical toLatin1() frames (0x06 for TextGroup, 0xFF for End). On 6.8.2, `arg(char)` forwards to QLatin1Char - the same Latin-1 mapping `QChar(char)` uses - so frames are byte-identical there too. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-fable-5 **Test case:** - Build against Qt 6.8.x: done for this PR with official 6.8.2 binaries on Linux - full build green on this branch and on unmodified development. - At minimum: the current build stays green (CI covers newer Qt only).
2026-07-26 13:30:15 +02:00
#include <QJsonObject>
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
#include <QJsonParseError>
infrastructure: harden the build for the minimum supported Qt version (#9510) #### Brief overview of PR changes/additions - Include QJson/QtCore headers directly in the 16 files that only reached those types through transitive includes; headers forward-declare where a reference suffices - Pass the MMCP command bytes to QString::arg() as explicit QChar (wire bytes unchanged) #### Motivation for adding to Mudlet An audit comment in #9011 reported that development does not build at the declared Qt 6.8.2 lower bound; building against official Qt 6.8.2 binaries shows it actually builds cleanly today, but only via transitive includes and arg() overload-set details that shift between Qt releases - this PR makes both explicit so the lower bound keeps working. #### Other info (issues closed, discussion etc) Relates to #9011 (not closed by this PR). Verification of the audit's two Qt 6.8.2 claims, done against official Qt 6.8.2 gcc_64 binaries: - Unmodified development configures and builds completely (387/387 targets, all functional tests link) at 6.8.2, so the reported QJson include errors and MMCP arg() compile failures did not reproduce. This branch builds green at 6.8.2 as well. - On the arg() claim specifically: 6.8.2's qstring.h declares `arg(char)` unconditionally, so the two live single-arg sites in MMCPServer.cpp already compiled. The genuinely 6.8.2-problematic pattern - multi-arg `.arg(char, ...)`, which on 6.8.2 resolves to `arg(char a, int fieldWidth)` and would silently eat the second byte as a field width - only occurs in commented-out code (MMCPServer.cpp around lines 534 and 1054). If that code is ever revived, it needs the QChar wrapping. - MMCP byte-equivalence: a small harness compiled against Qt 6.12 shows the old and new forms produce identical toLatin1() frames (0x06 for TextGroup, 0xFF for End). On 6.8.2, `arg(char)` forwards to QLatin1Char - the same Latin-1 mapping `QChar(char)` uses - so frames are byte-identical there too. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-fable-5 **Test case:** - Build against Qt 6.8.x: done for this PR with official 6.8.2 binaries on Linux - full build green on this branch and on unmodified development. - At minimum: the current build stays green (CI covers newer Qt only).
2026-07-26 13:30:15 +02:00
#include <QJsonValue>
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
#include <QMetaMethod>
#include <QPainter>
#include <QPixmap>
infrastructure: harden the build for the minimum supported Qt version (#9510) #### Brief overview of PR changes/additions - Include QJson/QtCore headers directly in the 16 files that only reached those types through transitive includes; headers forward-declare where a reference suffices - Pass the MMCP command bytes to QString::arg() as explicit QChar (wire bytes unchanged) #### Motivation for adding to Mudlet An audit comment in #9011 reported that development does not build at the declared Qt 6.8.2 lower bound; building against official Qt 6.8.2 binaries shows it actually builds cleanly today, but only via transitive includes and arg() overload-set details that shift between Qt releases - this PR makes both explicit so the lower bound keeps working. #### Other info (issues closed, discussion etc) Relates to #9011 (not closed by this PR). Verification of the audit's two Qt 6.8.2 claims, done against official Qt 6.8.2 gcc_64 binaries: - Unmodified development configures and builds completely (387/387 targets, all functional tests link) at 6.8.2, so the reported QJson include errors and MMCP arg() compile failures did not reproduce. This branch builds green at 6.8.2 as well. - On the arg() claim specifically: 6.8.2's qstring.h declares `arg(char)` unconditionally, so the two live single-arg sites in MMCPServer.cpp already compiled. The genuinely 6.8.2-problematic pattern - multi-arg `.arg(char, ...)`, which on 6.8.2 resolves to `arg(char a, int fieldWidth)` and would silently eat the second byte as a field width - only occurs in commented-out code (MMCPServer.cpp around lines 534 and 1054). If that code is ever revived, it needs the QChar wrapping. - MMCP byte-equivalence: a small harness compiled against Qt 6.12 shows the old and new forms produce identical toLatin1() frames (0x06 for TextGroup, 0xFF for End). On 6.8.2, `arg(char)` forwards to QLatin1Char - the same Latin-1 mapping `QChar(char)` uses - so frames are byte-identical there too. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-fable-5 **Test case:** - Build against Qt 6.8.x: done for this PR with official 6.8.2 binaries on Linux - full build green on this branch and on unmodified development. - At minimum: the current build stays green (CI covers newer Qt only).
2026-07-26 13:30:15 +02:00
#include <QSaveFile>
#include <QSizeF>
infrastructure: use std::chrono literals for time durations (#9493) #### Brief overview of PR changes/additions Convert raw millisecond integer literals at time-duration call sites to `std::chrono` literals, and add `#include <chrono>` to each touched translation unit. Examples: - `QTimer::singleShot(0, ...)` → `QTimer::singleShot(0ms, ...)` - `mpTimerReplay->setInterval(1000)` → `setInterval(1s)` - `mPendingTimer.start(60000)` → `start(1min)` - `QObject::startTimer(50)` → `startTimer(50ms)` - `QTest::qWait(100)` → `QTest::qWait(100ms)` - `QThread::msleep(10)` → `QThread::sleep(10ms)` This is a semantics-preserving refactor - every duration is kept exactly equal to before (e.g. `1000` ms becomes `1s`, `60000` ms becomes `1min`). No behavioural change. #### Motivation for adding to Mudlet Chrono literals make time durations self-documenting and type-safe. `1s` / `100ms` read unambiguously where a bare `1000` / `100` forces the reader to remember each API's unit, and the compiler now rejects unit mismatches. Only genuine duration arguments were converted - loop counts, scroll-line counts, sizes, ports and the like were deliberately left as plain integers. All targeted APIs provide `std::chrono` overloads in the minimum supported Qt (6.8.2): `QTimer::singleShot`/`start`/`setInterval` (5.8), `QObject::startTimer` (5.9), `QThread::sleep(std::chrono::nanoseconds)` (6.6) and `QTest::qWait(std::chrono::milliseconds)` (6.7). #### Other info (issues closed, discussion etc) Test case: the full application builds cleanly and the entire functional `ctest` suite passes. The only failing test is the known, pre-existing `PasswordMigrationTest` LSan exit-leak (GTK3/fontconfig noise), which is unrelated to this change. Assisted-by: Claude:claude-opus-4-8
2026-07-25 20:24:31 +02:00
#include <chrono>
2010-08-25 00:41:43 +02:00
infrastructure: use std::chrono literals for time durations (#9493) #### Brief overview of PR changes/additions Convert raw millisecond integer literals at time-duration call sites to `std::chrono` literals, and add `#include <chrono>` to each touched translation unit. Examples: - `QTimer::singleShot(0, ...)` → `QTimer::singleShot(0ms, ...)` - `mpTimerReplay->setInterval(1000)` → `setInterval(1s)` - `mPendingTimer.start(60000)` → `start(1min)` - `QObject::startTimer(50)` → `startTimer(50ms)` - `QTest::qWait(100)` → `QTest::qWait(100ms)` - `QThread::msleep(10)` → `QThread::sleep(10ms)` This is a semantics-preserving refactor - every duration is kept exactly equal to before (e.g. `1000` ms becomes `1s`, `60000` ms becomes `1min`). No behavioural change. #### Motivation for adding to Mudlet Chrono literals make time durations self-documenting and type-safe. `1s` / `100ms` read unambiguously where a bare `1000` / `100` forces the reader to remember each API's unit, and the compiler now rejects unit mismatches. Only genuine duration arguments were converted - loop counts, scroll-line counts, sizes, ports and the like were deliberately left as plain integers. All targeted APIs provide `std::chrono` overloads in the minimum supported Qt (6.8.2): `QTimer::singleShot`/`start`/`setInterval` (5.8), `QObject::startTimer` (5.9), `QThread::sleep(std::chrono::nanoseconds)` (6.6) and `QTest::qWait(std::chrono::milliseconds)` (6.7). #### Other info (issues closed, discussion etc) Test case: the full application builds cleanly and the entire functional `ctest` suite passes. The only failing test is the known, pre-existing `PasswordMigrationTest` LSan exit-leak (GTK3/fontconfig noise), which is unrelated to this change. Assisted-by: Claude:claude-opus-4-8
2026-07-25 20:24:31 +02:00
using namespace std::chrono_literals;
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
namespace {
// Restores font information from userData that was stored during binary serialization.
// Font data is stored as "family|pointSize|weight|italic" to avoid binary format version changes.
void restoreLabelFontFromUserData(TMapLabel& label, int labelId, QMap<QString, QString>& userData)
{
const QString fontKey = qsl("system.labelFont_%1").arg(labelId);
if (userData.contains(fontKey)) {
const QStringList fontParts = userData.take(fontKey).split(QLatin1Char('|'));
if (fontParts.size() == 4) {
label.font = QFont(fontParts.at(0), fontParts.at(1).toInt(), fontParts.at(2).toInt(), fontParts.at(3).toInt() != 0);
} else {
qWarning("TMap: Failed to parse font data for label %d, expected 4 parts but got %lld", labelId, fontParts.size());
}
}
}
// Outline color data is stored as "r|g|b|a" to avoid binary format version changes.
void restoreLabelOutlineColorFromUserData(TMapLabel& label, int labelId, QMap<QString, QString>& userData)
{
const QString colorKey = qsl("system.labelOutlineColor_%1").arg(labelId);
if (userData.contains(colorKey)) {
const QStringList colorParts = userData.take(colorKey).split(QLatin1Char('|'));
if (colorParts.size() == 4) {
label.outlineColor = QColor(colorParts.at(0).toInt(), colorParts.at(1).toInt(), colorParts.at(2).toInt(), colorParts.at(3).toInt());
} else {
qWarning("TMap: Failed to parse outline color data for label %d, expected 4 parts but got %lld", labelId, colorParts.size());
}
}
}
} // anonymous namespace
TMap::TMap(Host* pH, const QString& profileName)
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
: mDefaultAreaName(tr("Default Area"))
, mUnnamedAreaName(tr("Unnamed Area"))
improve: improve memory safety by using smart pointers (#9239) ### Refactor: replace raw pointer ownership with smart pointers across core subsystems #### Brief overview of PR changes/additions Replaces raw pointer ownership patterns with `std::unique_ptr` and `std::map` across several core subsystems: - **Host**: `mStopWatchMap` (`QMap<int, stopWatch*>` → `std::map<int, unique_ptr<stopWatch>>`), `profileShortcuts` (`QMap<QString, QKeySequence*>` → `std::map<QString, unique_ptr<QKeySequence>>`). Removes `qDeleteAll` in destructor and `delete mMMCPServer`. - **TMap**: `mpRoomDB` raw pointer → `unique_ptr` - **VarUnit**: `base` raw pointer → `unique_ptr` - **TTrigger**: condition map storage converted to `unique_ptr`, destructor simplified - **discord**: handler and presence maps converted from raw pointer `QMap` to `unique_ptr` + `std::map` - **Updater**: `mFeed` and `mUpdateDialog` converted to `unique_ptr` #### Motivation for adding to Mudlet These patterns were identified as sources of memory leaks and potential use-after-free bugs. Using smart pointers makes ownership explicit, eliminates manual cleanup code, and ensures correct destruction even on early-exit paths. #### Other info (issues closed, discussion etc) sorry this one is still pretty big, but most of the changes are the same for each thing so reviewing them together probably makes sense. sadly there isn't much to see here other than no slow uptick of heap size :-[ Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:42:09 +12:00
, mpRoomDB(std::make_unique<TRoomDB>(this))
, mpViewManager(new TMapViewManager(pH, this))
, mpHost(pH)
, mProfileName(profileName)
2010-08-25 00:41:43 +02:00
{
Infrastructure: move away from constructor initialisation lists - part 2 (#5937) For classes from "T2*" to "TM*" (approximately)... I have steered away from using `{}` to initialise simple, POD data types in favour of explicitly stating what their default values are. Also: * remove unused `(QColor) TAction::mButtonColor` and it's associated getter and setter. Also remove the save code from the `XMLexport` class and ensure it is skipped and silently discarded in the load code in `XMLimport`. * Make `private` some members of the `TFlipButton` class that probably weren't ever intended to be `public` * Remove unneeded named argument for `lua_State*` type in many (but not all) function declarations in `TLuaInterpreter.h` file - they aren't needed and whether an `L` was present or not seems to entirely down to the whim of the individual coder of each function...! * Rejig some of the initiliasations in the `TLuaInterpreter` class * Refactor a chunk of code n the `TMap` class used to (re)initialise the 16 colours user settable from the preferences dialogue to a method: `(void) TMap::restore16ColorSet()` - so that it can be used in three other places as well as the constuctor. * Remove unused `(int) T2DMap::gzoom`. * Add missing `TMediaData.h` file to qmake project file. Note: `QPointer<T>` instances do NOT need initialisation, they are automagically instantiated with a `nullptr` value. Revised to change code to fit in with PR #6133 There were some pre-Qt 5.14.0 version checks that are no longer relevant. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2022-06-27 20:36:51 +01:00
restore16ColorSet();
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
// TODO: https://github.com/Mudlet/Mudlet/issues/6436
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
// According to Qt Docs we should really only have one of these
// (QNetworkAccessManager) for the whole application, but: each profile's
// TLuaInterpreter; each profile's ctelnet and now each profile's TMap
// (was dlgMapper) instance has one...!
mpNetworkAccessManager = new QNetworkAccessManager(this);
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
mMapInfoContributorManager = new MapInfoContributorManager(this, pH);
connect(mpNetworkAccessManager, &QNetworkAccessManager::finished, this, &TMap::slot_replyFinished);
2010-08-25 00:41:43 +02:00
}
TMap::~TMap()
{
if (!mStoredMessages.isEmpty()) {
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
qWarning() << "TMap::~TMap() Instance being destroyed before it could display some messages,\n"
<< "messages are:\n"
<< "------------";
for (const auto& message : std::as_const(mStoredMessages)) {
qWarning() << message << "\n------------";
}
}
2014-08-27 20:24:25 -07:00
}
void TMap::mapClear()
{
2013-03-22 12:47:58 +01:00
mpRoomDB->clearMapDB();
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
mEnvColors.clear();
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
mRoomIdHash.clear();
mTargetID = 0;
mPathList.clear();
mDirList.clear();
mWeightList.clear();
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
mCustomEnvColors.clear();
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
// Need to restore the default colours:
Infrastructure: move away from constructor initialisation lists - part 2 (#5937) For classes from "T2*" to "TM*" (approximately)... I have steered away from using `{}` to initialise simple, POD data types in favour of explicitly stating what their default values are. Also: * remove unused `(QColor) TAction::mButtonColor` and it's associated getter and setter. Also remove the save code from the `XMLexport` class and ensure it is skipped and silently discarded in the load code in `XMLimport`. * Make `private` some members of the `TFlipButton` class that probably weren't ever intended to be `public` * Remove unneeded named argument for `lua_State*` type in many (but not all) function declarations in `TLuaInterpreter.h` file - they aren't needed and whether an `L` was present or not seems to entirely down to the whim of the individual coder of each function...! * Rejig some of the initiliasations in the `TLuaInterpreter` class * Refactor a chunk of code n the `TMap` class used to (re)initialise the 16 colours user settable from the preferences dialogue to a method: `(void) TMap::restore16ColorSet()` - so that it can be used in three other places as well as the constuctor. * Remove unused `(int) T2DMap::gzoom`. * Add missing `TMediaData.h` file to qmake project file. Note: `QPointer<T>` instances do NOT need initialisation, they are automagically instantiated with a `nullptr` value. Revised to change code to fit in with PR #6133 There were some pre-Qt 5.14.0 version checks that are no longer relevant. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2022-06-27 20:36:51 +01:00
restore16ColorSet();
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
roomidToIndex.clear();
edgeHash.clear();
locations.clear();
mMapGraphNeedsUpdate = true;
mNewMove = true;
mVersion = mDefaultVersion;
mUserData.clear();
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
// mSaveVersion is not reset - so that any new Mudlet map file saves are to
// whatever version was previously set/deduced
// Must also reset the mapper area selection control to reflect that it now
// only has the "Default Area" after TRoomDB::clearMapDB() has been run.
if (mpMapper) {
mpMapper->updateAreaComboBox();
auto map = mpMapper->mp2dMap;
if (map) {
map->mMultiSelectionListWidget.clear();
map->mMultiSelectionListWidget.hide();
}
}
}
// The supplied message should contain a localised message and no "WARNING:" or other prefixes:
void TMap::logError(const QString& msg)
{
if (mpHost->mpEditorDialog) {
/*: Used to print a map error in the Errors console in the Editor, %1 is the
message text and a line-feed is also appended.*/
mpHost->mpEditorDialog->mpErrorConsole->print(tr("[MAP ERROR:] %1").arg(msg).append(QChar::LineFeed), QColor(255, 128, 0), QColor(Qt::black));
}
}
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
// Not used:
//void TMap::exportMapToDatabase()
//{
// QString dbName = QFileDialog::getSaveFileName( 0, "Chose db file name." );
// QString script = QString("exportMapToDatabse([[%1]])").arg(dbName);
// mpHost->mLuaInterpreter.compileAndExecuteScript( script );
//}
//void TMap::importMapFromDatabase()
//{
// QString dbName = QFileDialog::getOpenFileName( 0, "Chose db file name." );
// QString script = QString("importMapFromDatabase([[%1]])").arg(dbName);
// mpHost->mLuaInterpreter.compileAndExecuteScript( script );
//}
2011-06-16 09:49:34 +02:00
bool TMap::setRoomArea(int id, int area, bool deferAreaRecalculations)
2011-06-16 09:49:34 +02:00
{
TRoom* pR = mpRoomDB->getRoom(id);
if (!pR) {
logError(tr("Can not set room with RoomID %1 to AreaID %2. Room does not exist!").arg(QString::number(id), QString::number(area)));
BugFix: Treat and prevent further duplicate or empty map area names Some steps had previously been taken to enforce no duplicate area names when importing an XML map or when adding a new name but other mechanisms were left unchecked, specifically this was when renaming an existing area. This commit adds a number of validation steps to many of the lua functions that manipulate areas and their names. This includes taking steps when creating a new TArea instance to ensure a suitable area name is created and added to the areaNamesMap which may be overwritten if a valid (non-empty, non-duplicate) name is provided at the time or later. This avoids problems with the Area selection widget on the 2 or 3D Map Display and the lua getAreaTable() function, neither of which will handle duplicate area names and for the former, does not handle nameless areas well either. The deleteArea() function could take either an area Id or a name as the target of its action so the area that is to be deleted is now not subject to any ambiguity if supplied as a name! Should a map file be loaded where empty or duplicated area names are found these will be "fixed" and warning messages inserted onto the main profile to explain what has happened. The user will only get this once per map file as there should now be no way to modified the map file to have either of these issues. The code that builds the area selection widget is revised to handle the corner cases of two areas that have the same letters in their name but the cases vary (the widget is sorted by name in a case insensitive manner) which previously was not handled (same as duplicate names were not). As a side effect of revising the TLuaInterpreter Class, area names containing non-ASCII characters can now be handled - they will be passed through the lua subsystem using the UTF-8 encoding. *** This commit is a reworking of one that produced a QMessageBox to alert and advised the user what was happening - that was deemed to be too intrusive so this version instead displays the information in the console - as such the detail of the renaming has to be shown now whereas the dialog solution had the option of providing it as "Show Details..." to display it only if requested at the time. *** Additionally, the lua setAreaName(areaId, newAreaName) has been extended to allow the existing area to be specified as a name (string) as well as an Id as we can now uniquely identify it by that means. This now matches the behaviour of deleteArea which already acts in that manner. It also means a user script can use "setAreaNAme(oldName, newName)" to rename an area without concern about determining the area Id. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-09 03:51:50 +00:00
return false;
}
TArea* pA = mpRoomDB->getArea(area);
if (!pA) {
// Uh oh, the area doesn't seem to exist as a TArea instance, let's check
// to see if it exists as a name only:
if (!mpRoomDB->getAreaNamesMap().contains(area)) {
// Ah, no it doesn't so moan:
logError(tr("Can not set room with RoomID %1 to AreaID %2. Area does not exist!").arg(QString::number(id), QString::number(area)));
return false;
}
// If got to this point then there is NOT a TArea instance for the given
// area Id but there is a Name - and the pR->setArea(...) call WILL
// instantiate the required TArea structure - this seems a bit twisty
// and convoluted, but it was how previous code was wired up and we need
// to retain the API for the lua subsystem...
}
2011-06-16 09:49:34 +02:00
const bool result = pR->setArea(area, deferAreaRecalculations);
if (result) {
Revise: massage Area Exit data to required format and ensure it is correct Rename: (void)TArea::fast_ausgaengeBestimmen(int) ==> TArea::determineAreaExitsOfRoom (void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits (const)(QList<int>)TArea::getAreaExits() const ==> TArea::getAreaExitRoomIds() Add new method to return area exit data in new, wanted format: (const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const In preparation to revising internal storage representation of area exit data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member from public to private area of class. To permit save and load the following have had to be made friends of the TArea class: (bool)TMap::serialize( QDataStream & ) and (bool)TMap::restore( QString ) Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on current and all previous map file format versions, will not be needed on future version as the code to manage the areaExits data is now functional. Previous code would have done this only for versions prior to 14 files (current is 16) or if the lua function auditAreas() was manually run. In passing also modified code that "fixed-up" "old style" map labels so that it is no longer run on current version files and pushes any messages that that creates into the main profile console instead of using standard C++ cout calls which we deprecate now. All code blocks that have been touched by this series of commits have been re-formatted to current styles. Update copyrights on all files touched that have not already been marked as having been edited by myself. Revised TLuaInterpreter::getAreaExits(...) to take a second optional Boolean that if present and true cause it to return data about the area exit directions and the destination rooms, if false or omitted, returns only the rooms in the area that have exits out of it, reproducing the previous implementation. In either case the result is a table if there are area exits (or a nil for an isolate area without exits); two additional values are returned an informative, translatable, text message and an integer status code that reflects the same information. When moving a series of rooms to a different area via the 2D mapper's GUI the recalculations for the area extremes {by TArea::calcSpan()} and the out of area exits {by TArea::determineAreaExits()} can now be deferred until the last room has been moved by passing a third true (boolean) argument to TMap::setRoomArea(...) which defaults to false for other single room at a time usages. Though that method keeps a local copy of the areas that have been modified and thus need updating, should the last room NOT be processed (null TRooo pointer for room Id) a publicly accessible "mIsDirty" flag is also used so that recovery code can identify and clean up those affected areas otherwise. It is possible that this flag may be useful in other situations, such as when moving or adding multiple rooms WITHIN an area. *** This commit has been rebased so it's history might not be the same as someone else's copy of it *** Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-05 01:20:15 +00:00
mMapGraphNeedsUpdate = true;
setUnsaved(__func__);
Revise: massage Area Exit data to required format and ensure it is correct Rename: (void)TArea::fast_ausgaengeBestimmen(int) ==> TArea::determineAreaExitsOfRoom (void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits (const)(QList<int>)TArea::getAreaExits() const ==> TArea::getAreaExitRoomIds() Add new method to return area exit data in new, wanted format: (const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const In preparation to revising internal storage representation of area exit data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member from public to private area of class. To permit save and load the following have had to be made friends of the TArea class: (bool)TMap::serialize( QDataStream & ) and (bool)TMap::restore( QString ) Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on current and all previous map file format versions, will not be needed on future version as the code to manage the areaExits data is now functional. Previous code would have done this only for versions prior to 14 files (current is 16) or if the lua function auditAreas() was manually run. In passing also modified code that "fixed-up" "old style" map labels so that it is no longer run on current version files and pushes any messages that that creates into the main profile console instead of using standard C++ cout calls which we deprecate now. All code blocks that have been touched by this series of commits have been re-formatted to current styles. Update copyrights on all files touched that have not already been marked as having been edited by myself. Revised TLuaInterpreter::getAreaExits(...) to take a second optional Boolean that if present and true cause it to return data about the area exit directions and the destination rooms, if false or omitted, returns only the rooms in the area that have exits out of it, reproducing the previous implementation. In either case the result is a table if there are area exits (or a nil for an isolate area without exits); two additional values are returned an informative, translatable, text message and an integer status code that reflects the same information. When moving a series of rooms to a different area via the 2D mapper's GUI the recalculations for the area extremes {by TArea::calcSpan()} and the out of area exits {by TArea::determineAreaExits()} can now be deferred until the last room has been moved by passing a third true (boolean) argument to TMap::setRoomArea(...) which defaults to false for other single room at a time usages. Though that method keeps a local copy of the areas that have been modified and thus need updating, should the last room NOT be processed (null TRooo pointer for room Id) a publicly accessible "mIsDirty" flag is also used so that recovery code can identify and clean up those affected areas otherwise. It is possible that this flag may be useful in other situations, such as when moving or adding multiple rooms WITHIN an area. *** This commit has been rebased so it's history might not be the same as someone else's copy of it *** Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-05 01:20:15 +00:00
}
return result;
2011-01-11 08:44:38 +01:00
}
bool TMap::addRoom(int id)
2010-09-07 20:35:32 +02:00
{
if (mpRoomDB->addRoom(id)) {
mMapGraphNeedsUpdate = true;
setUnsaved(__func__);
return true;
}
return false;
2010-09-07 20:35:32 +02:00
}
bool TMap::setRoomCoordinates(int id, int x, int y, int z)
2010-09-07 20:35:32 +02:00
{
TRoom* pR = mpRoomDB->getRoom(id);
if (!pR) {
return false;
}
2010-09-07 20:35:32 +02:00
const int oldX = pR->x();
const int oldY = pR->y();
const int oldZ = pR->z();
if (oldX != x || oldY != y || oldZ != z) {
TArea* pA = mpRoomDB->getArea(pR->getArea());
if (pA) {
// Atomically update both indices for any coordinate change.
pA->moveRoom(id, oldZ, oldX, oldY, z, x, y);
}
}
Infrastructure: make TRoom coordinates private (#7539) #### Summary of PR Changes/Additions Makes the coordinate members of the `TRoom` class private so that access to them can be tracked via methods to set and get them. #### Motivation for Adding to Mudlet This is so that the setters can then subsequently include any extra code that needs to be aware when the room is moved. I intend to improve the detection of rooms being placed in the same position but realised this would be a good preliminary step. #### Additional Information (related issues, discussions, etc.) Removes some dead code setting but not using `(int) quads` and `(int) verts` in `(void) GLWidget::paintGL()` Also using the mouse to drag and thus move selected rooms when those rooms were on different levels would squash them all down to be on the same z-coordinate as the "highlighted centre of the selection" room. This is not as helpful it might seem and instead increased the likelihood of causing room collisions - so now each room will retain it's z coordinate if it is not on the same level as the centre of the multiple room selection. Also move code that likely needs to be run whenever rooms are added/removed/moved within an area to a common block of code (`(void) TArea::clean()`) to help keep things DRY. I intend to put code to update a per area record of rooms that are in the same place within that block in the future - so that the record can be reused without having to be repeatedly recalculated, especially in the paint event for the 2D mapper. --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2024-12-09 14:29:13 +00:00
pR->setCoordinates(x, y, z);
2010-12-28 23:31:03 +01:00
setUnsaved(__func__);
2010-09-07 20:35:32 +02:00
return true;
}
int compSign(int a, int b)
{
return (a < 0) == (b < 0);
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
// Will connect the exit stub in the indicated direction to a suitable room
// i.e. in the "right" (x,y,z) location AND with a stub in the reverse direction
// IN THE SAME AREA as the fromRoomId numbered room and also create the exit in
// the reverse direction from the other room - otherwise it will report the
// reason why it cannot.
QString TMap::connectExitStubByDirection(const int fromRoomId, const int dirType)
2013-03-22 12:47:58 +01:00
{
Infrastructure: move away from constructor initialisation lists - part 2 (#5937) For classes from "T2*" to "TM*" (approximately)... I have steered away from using `{}` to initialise simple, POD data types in favour of explicitly stating what their default values are. Also: * remove unused `(QColor) TAction::mButtonColor` and it's associated getter and setter. Also remove the save code from the `XMLexport` class and ensure it is skipped and silently discarded in the load code in `XMLimport`. * Make `private` some members of the `TFlipButton` class that probably weren't ever intended to be `public` * Remove unneeded named argument for `lua_State*` type in many (but not all) function declarations in `TLuaInterpreter.h` file - they aren't needed and whether an `L` was present or not seems to entirely down to the whim of the individual coder of each function...! * Rejig some of the initiliasations in the `TLuaInterpreter` class * Refactor a chunk of code n the `TMap` class used to (re)initialise the 16 colours user settable from the preferences dialogue to a method: `(void) TMap::restore16ColorSet()` - so that it can be used in three other places as well as the constuctor. * Remove unused `(int) T2DMap::gzoom`. * Add missing `TMediaData.h` file to qmake project file. Note: `QPointer<T>` instances do NOT need initialisation, they are automagically instantiated with a `nullptr` value. Revised to change code to fit in with PR #6133 There were some pre-Qt 5.14.0 version checks that are no longer relevant. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2022-06-27 20:36:51 +01:00
Q_ASSERT_X(scmUnitVectors.contains(dirType), "TMap::connectExitStubByDirection(...)", "there is no unitVector.value() for the given dirType");
Q_ASSERT_X(scmReverseDirections.contains(dirType), "TMap::connectExitStubByDirection(...)", "there is no scmReverseDirections.value() for the given dirType");
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
TRoom* pFromR = mpRoomDB->getRoom(fromRoomId);
if (!pFromR) {
return qsl("fromID (%1) does not exist").arg(fromRoomId);
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
}
const int area = pFromR->getArea();
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
// This will get converted to a positive value on first use:
int minDistance = -1;
int minDistanceRoom = 0;
int meanSquareDistance = 0;
if (!pFromR->exitStubs.contains(dirType)) {
return qsl("fromID (%1) does not have an exit stub in the given direction '%2' (%3)").arg(QString::number(fromRoomId), TRoom::dirCodeToString(dirType), QString::number(dirType));
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
const int reverseDir = scmReverseDirections.value(dirType);
const QVector3D unitVector = scmUnitVectors.value(dirType);
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
// QVector3D is composed of floating point values so we need to round them
// if we want to assign them to integral variables without compiler warnings!
const int ux = qRound(unitVector.x());
const int uy = qRound(unitVector.y());
const int uz = qRound(unitVector.z());
Infrastructure: make TRoom coordinates private (#7539) #### Summary of PR Changes/Additions Makes the coordinate members of the `TRoom` class private so that access to them can be tracked via methods to set and get them. #### Motivation for Adding to Mudlet This is so that the setters can then subsequently include any extra code that needs to be aware when the room is moved. I intend to improve the detection of rooms being placed in the same position but realised this would be a good preliminary step. #### Additional Information (related issues, discussions, etc.) Removes some dead code setting but not using `(int) quads` and `(int) verts` in `(void) GLWidget::paintGL()` Also using the mouse to drag and thus move selected rooms when those rooms were on different levels would squash them all down to be on the same z-coordinate as the "highlighted centre of the selection" room. This is not as helpful it might seem and instead increased the likelihood of causing room collisions - so now each room will retain it's z coordinate if it is not on the same level as the centre of the multiple room selection. Also move code that likely needs to be run whenever rooms are added/removed/moved within an area to a common block of code (`(void) TArea::clean()`) to help keep things DRY. I intend to put code to update a per area record of rooms that are in the same place within that block in the future - so that the record can be reused without having to be repeatedly recalculated, especially in the paint event for the 2D mapper. --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2024-12-09 14:29:13 +00:00
const int rx = pFromR->x();
const int ry = pFromR->y();
const int rz = pFromR->z();
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
int dx = 0;
int dy = 0;
int dz = 0;
TArea* pA = mpRoomDB->getArea(area);
if (!pA) {
return qsl("fromID (%1) room does not have an area").arg(fromRoomId);
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
QSetIterator<int> itRoom(pA->getAreaRooms());
while (itRoom.hasNext()) {
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
auto toRoom = itRoom.next();
auto pToR = mpRoomDB->getRoom(toRoom);
if (!pToR || pToR->getId() == fromRoomId) {
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
continue;
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
// New test - does this room have a stub exit in the wanted reverse
// direction:
if (!pToR->exitStubs.contains(reverseDir)) {
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
continue;
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
if (uz) {
Infrastructure: make TRoom coordinates private (#7539) #### Summary of PR Changes/Additions Makes the coordinate members of the `TRoom` class private so that access to them can be tracked via methods to set and get them. #### Motivation for Adding to Mudlet This is so that the setters can then subsequently include any extra code that needs to be aware when the room is moved. I intend to improve the detection of rooms being placed in the same position but realised this would be a good preliminary step. #### Additional Information (related issues, discussions, etc.) Removes some dead code setting but not using `(int) quads` and `(int) verts` in `(void) GLWidget::paintGL()` Also using the mouse to drag and thus move selected rooms when those rooms were on different levels would squash them all down to be on the same z-coordinate as the "highlighted centre of the selection" room. This is not as helpful it might seem and instead increased the likelihood of causing room collisions - so now each room will retain it's z coordinate if it is not on the same level as the centre of the multiple room selection. Also move code that likely needs to be run whenever rooms are added/removed/moved within an area to a common block of code (`(void) TArea::clean()`) to help keep things DRY. I intend to put code to update a per area record of rooms that are in the same place within that block in the future - so that the record can be reused without having to be repeatedly recalculated, especially in the paint event for the 2D mapper. --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2024-12-09 14:29:13 +00:00
dz = pToR->z() - rz;
if (!compSign(dz, uz) || !dz) {
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
continue;
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
} else {
//to avoid lower/upper floors from stealing stubs
Infrastructure: make TRoom coordinates private (#7539) #### Summary of PR Changes/Additions Makes the coordinate members of the `TRoom` class private so that access to them can be tracked via methods to set and get them. #### Motivation for Adding to Mudlet This is so that the setters can then subsequently include any extra code that needs to be aware when the room is moved. I intend to improve the detection of rooms being placed in the same position but realised this would be a good preliminary step. #### Additional Information (related issues, discussions, etc.) Removes some dead code setting but not using `(int) quads` and `(int) verts` in `(void) GLWidget::paintGL()` Also using the mouse to drag and thus move selected rooms when those rooms were on different levels would squash them all down to be on the same z-coordinate as the "highlighted centre of the selection" room. This is not as helpful it might seem and instead increased the likelihood of causing room collisions - so now each room will retain it's z coordinate if it is not on the same level as the centre of the multiple room selection. Also move code that likely needs to be run whenever rooms are added/removed/moved within an area to a common block of code (`(void) TArea::clean()`) to help keep things DRY. I intend to put code to update a per area record of rooms that are in the same place within that block in the future - so that the record can be reused without having to be repeatedly recalculated, especially in the paint event for the 2D mapper. --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2024-12-09 14:29:13 +00:00
if (pToR->z() != rz) {
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
continue;
}
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
if (ux) {
Infrastructure: make TRoom coordinates private (#7539) #### Summary of PR Changes/Additions Makes the coordinate members of the `TRoom` class private so that access to them can be tracked via methods to set and get them. #### Motivation for Adding to Mudlet This is so that the setters can then subsequently include any extra code that needs to be aware when the room is moved. I intend to improve the detection of rooms being placed in the same position but realised this would be a good preliminary step. #### Additional Information (related issues, discussions, etc.) Removes some dead code setting but not using `(int) quads` and `(int) verts` in `(void) GLWidget::paintGL()` Also using the mouse to drag and thus move selected rooms when those rooms were on different levels would squash them all down to be on the same z-coordinate as the "highlighted centre of the selection" room. This is not as helpful it might seem and instead increased the likelihood of causing room collisions - so now each room will retain it's z coordinate if it is not on the same level as the centre of the multiple room selection. Also move code that likely needs to be run whenever rooms are added/removed/moved within an area to a common block of code (`(void) TArea::clean()`) to help keep things DRY. I intend to put code to update a per area record of rooms that are in the same place within that block in the future - so that the record can be reused without having to be repeatedly recalculated, especially in the paint event for the 2D mapper. --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2024-12-09 14:29:13 +00:00
dx = pToR->x() - rx;
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
if (!compSign(dx, ux) || !dx) {
//we do !dx pRto make sure we have a component in the desired direction
continue;
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
} else {
//to avoid rooms on same plane from stealing stubs
Infrastructure: make TRoom coordinates private (#7539) #### Summary of PR Changes/Additions Makes the coordinate members of the `TRoom` class private so that access to them can be tracked via methods to set and get them. #### Motivation for Adding to Mudlet This is so that the setters can then subsequently include any extra code that needs to be aware when the room is moved. I intend to improve the detection of rooms being placed in the same position but realised this would be a good preliminary step. #### Additional Information (related issues, discussions, etc.) Removes some dead code setting but not using `(int) quads` and `(int) verts` in `(void) GLWidget::paintGL()` Also using the mouse to drag and thus move selected rooms when those rooms were on different levels would squash them all down to be on the same z-coordinate as the "highlighted centre of the selection" room. This is not as helpful it might seem and instead increased the likelihood of causing room collisions - so now each room will retain it's z coordinate if it is not on the same level as the centre of the multiple room selection. Also move code that likely needs to be run whenever rooms are added/removed/moved within an area to a common block of code (`(void) TArea::clean()`) to help keep things DRY. I intend to put code to update a per area record of rooms that are in the same place within that block in the future - so that the record can be reused without having to be repeatedly recalculated, especially in the paint event for the 2D mapper. --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2024-12-09 14:29:13 +00:00
if (pToR->x() != rx) {
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
continue;
}
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
if (uy) {
Infrastructure: make TRoom coordinates private (#7539) #### Summary of PR Changes/Additions Makes the coordinate members of the `TRoom` class private so that access to them can be tracked via methods to set and get them. #### Motivation for Adding to Mudlet This is so that the setters can then subsequently include any extra code that needs to be aware when the room is moved. I intend to improve the detection of rooms being placed in the same position but realised this would be a good preliminary step. #### Additional Information (related issues, discussions, etc.) Removes some dead code setting but not using `(int) quads` and `(int) verts` in `(void) GLWidget::paintGL()` Also using the mouse to drag and thus move selected rooms when those rooms were on different levels would squash them all down to be on the same z-coordinate as the "highlighted centre of the selection" room. This is not as helpful it might seem and instead increased the likelihood of causing room collisions - so now each room will retain it's z coordinate if it is not on the same level as the centre of the multiple room selection. Also move code that likely needs to be run whenever rooms are added/removed/moved within an area to a common block of code (`(void) TArea::clean()`) to help keep things DRY. I intend to put code to update a per area record of rooms that are in the same place within that block in the future - so that the record can be reused without having to be repeatedly recalculated, especially in the paint event for the 2D mapper. --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2024-12-09 14:29:13 +00:00
dy = pToR->y() - ry;
//if the sign is the SAME here we keep it b/c we flip our y coordinate.
if (compSign(dy, uy) || !dy) {
continue;
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
} else {
//to avoid rooms on same plane from stealing stubs
Infrastructure: make TRoom coordinates private (#7539) #### Summary of PR Changes/Additions Makes the coordinate members of the `TRoom` class private so that access to them can be tracked via methods to set and get them. #### Motivation for Adding to Mudlet This is so that the setters can then subsequently include any extra code that needs to be aware when the room is moved. I intend to improve the detection of rooms being placed in the same position but realised this would be a good preliminary step. #### Additional Information (related issues, discussions, etc.) Removes some dead code setting but not using `(int) quads` and `(int) verts` in `(void) GLWidget::paintGL()` Also using the mouse to drag and thus move selected rooms when those rooms were on different levels would squash them all down to be on the same z-coordinate as the "highlighted centre of the selection" room. This is not as helpful it might seem and instead increased the likelihood of causing room collisions - so now each room will retain it's z coordinate if it is not on the same level as the centre of the multiple room selection. Also move code that likely needs to be run whenever rooms are added/removed/moved within an area to a common block of code (`(void) TArea::clean()`) to help keep things DRY. I intend to put code to update a per area record of rooms that are in the same place within that block in the future - so that the record can be reused without having to be repeatedly recalculated, especially in the paint event for the 2D mapper. --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2024-12-09 14:29:13 +00:00
if (pToR->y() != ry) {
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
continue;
}
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
meanSquareDistance = dx * dx + dy * dy + dz * dz;
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
if (Q_UNLIKELY(minDistance == -1) || (meanSquareDistance < minDistance)) {
// The first alternative above is the initialisaton case:
minDistanceRoom = toRoom;
minDistance = meanSquareDistance;
}
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
if (minDistanceRoom) {
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
auto pToR = mpRoomDB->getRoom(minDistanceRoom);
if (!pToR) {
// Technically this should be redundant as we have already checked
// that this room existed in the above while() loop!
return qsl("nearest room in the indicated direction (%1) does not exist").arg(minDistanceRoom);
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
setExit(fromRoomId, minDistanceRoom, dirType);
Infrastructure: move away from constructor initialisation lists - part 2 (#5937) For classes from "T2*" to "TM*" (approximately)... I have steered away from using `{}` to initialise simple, POD data types in favour of explicitly stating what their default values are. Also: * remove unused `(QColor) TAction::mButtonColor` and it's associated getter and setter. Also remove the save code from the `XMLexport` class and ensure it is skipped and silently discarded in the load code in `XMLimport`. * Make `private` some members of the `TFlipButton` class that probably weren't ever intended to be `public` * Remove unneeded named argument for `lua_State*` type in many (but not all) function declarations in `TLuaInterpreter.h` file - they aren't needed and whether an `L` was present or not seems to entirely down to the whim of the individual coder of each function...! * Rejig some of the initiliasations in the `TLuaInterpreter` class * Refactor a chunk of code n the `TMap` class used to (re)initialise the 16 colours user settable from the preferences dialogue to a method: `(void) TMap::restore16ColorSet()` - so that it can be used in three other places as well as the constuctor. * Remove unused `(int) T2DMap::gzoom`. * Add missing `TMediaData.h` file to qmake project file. Note: `QPointer<T>` instances do NOT need initialisation, they are automagically instantiated with a `nullptr` value. Revised to change code to fit in with PR #6133 There were some pre-Qt 5.14.0 version checks that are no longer relevant. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2022-06-27 20:36:51 +01:00
setExit(minDistanceRoom, fromRoomId, scmReverseDirections.value(dirType));
setUnsaved(__func__);
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
return {};
}
return qsl("fromID (%1) does not have another room in the indicated direction '%2' (%3) with an exit stub in the reverse direction to connect to in its area")
.arg(QString::number(fromRoomId), TRoom::dirCodeToString(dirType), QString::number(dirType));
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
}
// Will connect an exit stub from the fromRoomId numbered room to the toRoomId
// numbered room and also connect the corresponding stub exit in the reverse
// direction of the toRoomId room back to the fromRoomId provided the second
// room has a stub in the reverse direction.
// Unlike the connectExitStubByDirection(...) method the relative placement of
// the two rooms is not considered - and indeed the toRoomId room need not be
// IN THE SAME AREA as the fromRoomId numbered room - otherwise it will report
// the reason why it cannot.
// It will only work if there is a single matching pair of stub exits between
// the two rooms - if there are more than one it will fail and invite the
// use of the Lua function with three arguments that include a direction and
// thus use connectExitStubByDirectionAndToId(...) instead:
QString TMap::connectExitStubByToId(const int fromRoomId, const int toRoomId)
{
auto pFromR = mpRoomDB->getRoom(fromRoomId);
if (!pFromR) {
return qsl("fromID (%1) does not exist").arg(fromRoomId);
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
}
if (toRoomId == fromRoomId) {
return qsl("fromID and toID are the same (%1)").arg(fromRoomId);
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
}
auto pToR = mpRoomDB->getRoom(toRoomId);
if (!pToR) {
return qsl("toID (%1) room does not exist").arg(toRoomId);
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
}
if (pFromR->exitStubs.isEmpty()) {
return qsl("fromID (%1) does not have any stub exits").arg(fromRoomId);
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
}
if (pToR->exitStubs.isEmpty()) {
return qsl("toID (%1) does not have any stub exits").arg(toRoomId);
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
}
QSet<int> const fromRoomStubs{pFromR->exitStubs.cbegin(), pFromR->exitStubs.cend()};
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
QListIterator<int> itToRoomStubs{pToR->exitStubs};
QSet<int> toReverseStubDirections;
while (itToRoomStubs.hasNext()) {
auto direction = itToRoomStubs.next();
Infrastructure: move away from constructor initialisation lists - part 2 (#5937) For classes from "T2*" to "TM*" (approximately)... I have steered away from using `{}` to initialise simple, POD data types in favour of explicitly stating what their default values are. Also: * remove unused `(QColor) TAction::mButtonColor` and it's associated getter and setter. Also remove the save code from the `XMLexport` class and ensure it is skipped and silently discarded in the load code in `XMLimport`. * Make `private` some members of the `TFlipButton` class that probably weren't ever intended to be `public` * Remove unneeded named argument for `lua_State*` type in many (but not all) function declarations in `TLuaInterpreter.h` file - they aren't needed and whether an `L` was present or not seems to entirely down to the whim of the individual coder of each function...! * Rejig some of the initiliasations in the `TLuaInterpreter` class * Refactor a chunk of code n the `TMap` class used to (re)initialise the 16 colours user settable from the preferences dialogue to a method: `(void) TMap::restore16ColorSet()` - so that it can be used in three other places as well as the constuctor. * Remove unused `(int) T2DMap::gzoom`. * Add missing `TMediaData.h` file to qmake project file. Note: `QPointer<T>` instances do NOT need initialisation, they are automagically instantiated with a `nullptr` value. Revised to change code to fit in with PR #6133 There were some pre-Qt 5.14.0 version checks that are no longer relevant. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2022-06-27 20:36:51 +01:00
Q_ASSERT_X(scmReverseDirections.contains(direction), "TMap::connectExitStubByToId(...)", "there is no scmReverseDirections.value() for a particular direction encountered");
toReverseStubDirections.insert(scmReverseDirections.value(direction));
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
}
QSet<int> usableStubDirections{fromRoomStubs};
usableStubDirections.detach();
usableStubDirections = usableStubDirections.intersect(toReverseStubDirections);
// Now we need to count how big this set is:
if (usableStubDirections.isEmpty()) {
return qsl("no pairs of reverse stubs found between rooms %1 and %2").arg(QString::number(fromRoomId), QString::number(toRoomId));
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
}
if (usableStubDirections.count() > 1) {
QStringList useableStubDirectionTexts;
QSetIterator<int> itUseableStub(usableStubDirections);
while (itUseableStub.hasNext()) {
auto direction = itUseableStub.next();
useableStubDirectionTexts << qsl("'%1' (%2)").arg(TRoom::dirCodeToString(direction), QString::number(direction));
}
return qsl("multiple pairs of reverse stubs found between rooms %1 and %2, please try again with the three argument function and one of the follow directions: %3")
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
.arg(QString::number(fromRoomId), QString::number(toRoomId), useableStubDirectionTexts.join(QLatin1String(", ")));
}
// else we must have just one direction:
const int usableStubDirection = *(usableStubDirections.constBegin());
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
setExit(fromRoomId, toRoomId, usableStubDirection);
Infrastructure: move away from constructor initialisation lists - part 2 (#5937) For classes from "T2*" to "TM*" (approximately)... I have steered away from using `{}` to initialise simple, POD data types in favour of explicitly stating what their default values are. Also: * remove unused `(QColor) TAction::mButtonColor` and it's associated getter and setter. Also remove the save code from the `XMLexport` class and ensure it is skipped and silently discarded in the load code in `XMLimport`. * Make `private` some members of the `TFlipButton` class that probably weren't ever intended to be `public` * Remove unneeded named argument for `lua_State*` type in many (but not all) function declarations in `TLuaInterpreter.h` file - they aren't needed and whether an `L` was present or not seems to entirely down to the whim of the individual coder of each function...! * Rejig some of the initiliasations in the `TLuaInterpreter` class * Refactor a chunk of code n the `TMap` class used to (re)initialise the 16 colours user settable from the preferences dialogue to a method: `(void) TMap::restore16ColorSet()` - so that it can be used in three other places as well as the constuctor. * Remove unused `(int) T2DMap::gzoom`. * Add missing `TMediaData.h` file to qmake project file. Note: `QPointer<T>` instances do NOT need initialisation, they are automagically instantiated with a `nullptr` value. Revised to change code to fit in with PR #6133 There were some pre-Qt 5.14.0 version checks that are no longer relevant. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2022-06-27 20:36:51 +01:00
setExit(toRoomId, fromRoomId, scmReverseDirections.value(usableStubDirection));
setUnsaved(__func__);
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
return {};
}
// Will connect an exit stub in the indicated direction from the fromRoomId
// numbered room to the toRoomId numbered room and also connect the
// corresponding stub exit in the reverse direction of the toRoomId room back to
// the fromRoomId provided the second room has a stub in the reverse direction.
// Unlike the connectExitStubByDirection(...) method the relative placement of
// the two rooms is not considered - and indeed the toRoomId room need not be
// IN THE SAME AREA as the fromRoomId numbered room - otherwise it will report
// the reason why it cannot.
QString TMap::connectExitStubByDirectionAndToId(const int fromRoomId, const int dirType, const int toRoomId)
{
Infrastructure: move away from constructor initialisation lists - part 2 (#5937) For classes from "T2*" to "TM*" (approximately)... I have steered away from using `{}` to initialise simple, POD data types in favour of explicitly stating what their default values are. Also: * remove unused `(QColor) TAction::mButtonColor` and it's associated getter and setter. Also remove the save code from the `XMLexport` class and ensure it is skipped and silently discarded in the load code in `XMLimport`. * Make `private` some members of the `TFlipButton` class that probably weren't ever intended to be `public` * Remove unneeded named argument for `lua_State*` type in many (but not all) function declarations in `TLuaInterpreter.h` file - they aren't needed and whether an `L` was present or not seems to entirely down to the whim of the individual coder of each function...! * Rejig some of the initiliasations in the `TLuaInterpreter` class * Refactor a chunk of code n the `TMap` class used to (re)initialise the 16 colours user settable from the preferences dialogue to a method: `(void) TMap::restore16ColorSet()` - so that it can be used in three other places as well as the constuctor. * Remove unused `(int) T2DMap::gzoom`. * Add missing `TMediaData.h` file to qmake project file. Note: `QPointer<T>` instances do NOT need initialisation, they are automagically instantiated with a `nullptr` value. Revised to change code to fit in with PR #6133 There were some pre-Qt 5.14.0 version checks that are no longer relevant. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2022-06-27 20:36:51 +01:00
Q_ASSERT_X(scmReverseDirections.contains(dirType), "TMap::connectExitStubByDirectionAndToId(...)", "there is no scmReverseDirections.value() for the given dirType");
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
auto pFromR = mpRoomDB->getRoom(fromRoomId);
if (!pFromR) {
return qsl("fromID (%1) does not exist").arg(fromRoomId);
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
}
if (toRoomId == fromRoomId) {
return qsl("fromID and toID are the same (%1)").arg(fromRoomId);
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
}
if (!pFromR->exitStubs.contains(dirType)) {
return qsl("fromID (%1) does not have an exit stub in the given direction '%2' (%3)").arg(QString::number(fromRoomId), TRoom::dirCodeToString(dirType), QString::number(dirType));
}
auto pToR = mpRoomDB->getRoom(toRoomId);
if (!pToR) {
return qsl("toID (%1) room does not exist").arg(toRoomId);
}
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
Infrastructure: move away from constructor initialisation lists - part 2 (#5937) For classes from "T2*" to "TM*" (approximately)... I have steered away from using `{}` to initialise simple, POD data types in favour of explicitly stating what their default values are. Also: * remove unused `(QColor) TAction::mButtonColor` and it's associated getter and setter. Also remove the save code from the `XMLexport` class and ensure it is skipped and silently discarded in the load code in `XMLimport`. * Make `private` some members of the `TFlipButton` class that probably weren't ever intended to be `public` * Remove unneeded named argument for `lua_State*` type in many (but not all) function declarations in `TLuaInterpreter.h` file - they aren't needed and whether an `L` was present or not seems to entirely down to the whim of the individual coder of each function...! * Rejig some of the initiliasations in the `TLuaInterpreter` class * Refactor a chunk of code n the `TMap` class used to (re)initialise the 16 colours user settable from the preferences dialogue to a method: `(void) TMap::restore16ColorSet()` - so that it can be used in three other places as well as the constuctor. * Remove unused `(int) T2DMap::gzoom`. * Add missing `TMediaData.h` file to qmake project file. Note: `QPointer<T>` instances do NOT need initialisation, they are automagically instantiated with a `nullptr` value. Revised to change code to fit in with PR #6133 There were some pre-Qt 5.14.0 version checks that are no longer relevant. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2022-06-27 20:36:51 +01:00
if (!pToR->exitStubs.contains(scmReverseDirections.value(dirType))) {
return qsl("toID (%1) does not have an exit stub in the reverse direction '%2' (%3) of that given '%4' (%5)")
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
.arg(QString::number(toRoomId),
Infrastructure: move away from constructor initialisation lists - part 2 (#5937) For classes from "T2*" to "TM*" (approximately)... I have steered away from using `{}` to initialise simple, POD data types in favour of explicitly stating what their default values are. Also: * remove unused `(QColor) TAction::mButtonColor` and it's associated getter and setter. Also remove the save code from the `XMLexport` class and ensure it is skipped and silently discarded in the load code in `XMLimport`. * Make `private` some members of the `TFlipButton` class that probably weren't ever intended to be `public` * Remove unneeded named argument for `lua_State*` type in many (but not all) function declarations in `TLuaInterpreter.h` file - they aren't needed and whether an `L` was present or not seems to entirely down to the whim of the individual coder of each function...! * Rejig some of the initiliasations in the `TLuaInterpreter` class * Refactor a chunk of code n the `TMap` class used to (re)initialise the 16 colours user settable from the preferences dialogue to a method: `(void) TMap::restore16ColorSet()` - so that it can be used in three other places as well as the constuctor. * Remove unused `(int) T2DMap::gzoom`. * Add missing `TMediaData.h` file to qmake project file. Note: `QPointer<T>` instances do NOT need initialisation, they are automagically instantiated with a `nullptr` value. Revised to change code to fit in with PR #6133 There were some pre-Qt 5.14.0 version checks that are no longer relevant. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2022-06-27 20:36:51 +01:00
TRoom::dirCodeToString(scmReverseDirections.value(dirType)),
QString::number(scmReverseDirections.value(dirType)),
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
TRoom::dirCodeToString(dirType),
QString::number(dirType));
}
setExit(fromRoomId, toRoomId, dirType);
Infrastructure: move away from constructor initialisation lists - part 2 (#5937) For classes from "T2*" to "TM*" (approximately)... I have steered away from using `{}` to initialise simple, POD data types in favour of explicitly stating what their default values are. Also: * remove unused `(QColor) TAction::mButtonColor` and it's associated getter and setter. Also remove the save code from the `XMLexport` class and ensure it is skipped and silently discarded in the load code in `XMLimport`. * Make `private` some members of the `TFlipButton` class that probably weren't ever intended to be `public` * Remove unneeded named argument for `lua_State*` type in many (but not all) function declarations in `TLuaInterpreter.h` file - they aren't needed and whether an `L` was present or not seems to entirely down to the whim of the individual coder of each function...! * Rejig some of the initiliasations in the `TLuaInterpreter` class * Refactor a chunk of code n the `TMap` class used to (re)initialise the 16 colours user settable from the preferences dialogue to a method: `(void) TMap::restore16ColorSet()` - so that it can be used in three other places as well as the constuctor. * Remove unused `(int) T2DMap::gzoom`. * Add missing `TMediaData.h` file to qmake project file. Note: `QPointer<T>` instances do NOT need initialisation, they are automagically instantiated with a `nullptr` value. Revised to change code to fit in with PR #6133 There were some pre-Qt 5.14.0 version checks that are no longer relevant. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2022-06-27 20:36:51 +01:00
setExit(toRoomId, fromRoomId, scmReverseDirections.value(dirType));
setUnsaved(__func__);
BugFix: try and make connectExitStub(...) work as per the API (#5395) * BugFix: try and make connectExitStub(...) work as per the API This PR should enable connectExitStub(...) to work as close to the existing published API as possible: * connectExitStub((integer) fromRoomID, (integer)toRoomID, (integer or string) direction) where direction is the initial(s) or full, lower-case, un-hypenated ENGLISH word for one of the 12 normal exit directions - this will make a two way exit between the given direction of the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but they must BOTH have stub exits in the required direction. * `connectExitStub((integer) fromRoomID, (integer) toRoomID)` - this will make a two way exit between the fromRoomID room to the toRoomID room AND the corresponding reverse direction exit from the toRoomID room. The rooms need not be the same Area but the fromRoomID must have only ONE stub exit with an opposite (reverse) direction one in the toRoomID one - either room can have other stub exits. Should there be more than one pair of stub exits a nil + error message will be produced listing the choices for the direction that can be passed to the three argument function call to make the exits wanted. * `connectExitStub((integer) fromRoomID, (integer or string) dirction)` - this will make a two way exit between the stub exit in the fromRoomID room to the NEAREST other room IN THE SAME AREA which has a stub exit in the reverse direction and which lies in the correct relative position (except for the `in`/`out` directions where this is not relevant). Should the direction be given as an integer in the range 1 to 12 this will be rejected (via a nil + error message) because it is ambiguous then whether the number represents a direction or a toRoomID. Potentially unlike the prior code, this version properly detects whether a string or number is supplied as the direction argument. Also: * to allow the reporting of the direction as a number and a string in error messages the `(QString) TRoom::dirCodeToString(const int)` method has been made `static` so that it can be used in the `TLuaInterpreter` class. * as indirectly mentioned above `(int) TLuaInterpreter::dirToNumber(lua_State*, int)` has been revised to check for a string or integer argument being examined - the prior code may not work as anticipated because it used `lua_isxxxx(...)` functions which can coerce the value they are dealing with (a number can be coerced into a string) - which messes with the logic. * in places in the revised methods the integer constant values have been replaced with the `DIR_XXXXX` values defined in the `TRoom` class header file. * to simplify (!) the coding the three different forms of the Lua API are implemented in three separate `(QString) TMap::connectExitStubByXxxx(...) methods which collectively replace the original `(void) TMap::connectExitStub(...)` one. They are responsible for generating most of the Lua API error messages for this function and they indicate success by returning an empty string. This should close #2386. Revise: add a suggestion to the user on how to proceed on a message Signed-off by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-10-02 21:09:23 +01:00
return {};
}
int TMap::createNewRoomID(int minimumId)
2010-09-07 20:35:32 +02:00
{
int _id = 0;
if (minimumId > 0) {
_id = minimumId - 1;
2010-09-07 20:35:32 +02:00
}
do {
; // Empty loop as increment done in test
} while (mpRoomDB->getRoom(++_id));
return _id;
2010-09-07 20:35:32 +02:00
}
bool TMap::setExit(int from, int to, int dir)
2010-09-07 20:35:32 +02:00
{
Backport: merge ten commits room "entrance" code from "release_30" to "development" branches, Commit 01 of 10 originally entitled: "fix for keeping reverse area exit map in sync with exit creation, adding, and deletion" Conflicts resolved in: src/TRoom.h Commit 02 of 10 originally entitled: "bug fix for entranceMap having reversed key and value" Conflicts resolved in: src/TRoomDB.cpp Commit 03 of 10 originally entitled: "removal of entranceMap cleanup" Conflicts resolved in: src/TRoomDB.cpp Commit 04 of 10 originally entitled: "BugFix: prevent crash in dlgRoomExits::initExits() on missing exit" Code deficiencies that remove rooms without properly updating connected rooms were causing segmentation faults because this method - perhaps foolishly - expected a room to exist when another room had an exit Id to the room given. This commit corrects any faulty normal exits now by resetting them to the no exit -1 value. Commit 05 of 10 originally entitled: "Fixup: prevent unneeded TRoom::setExit() calls from dlgRoomExits class" Each individual call to TRoom::setExit((int)exitRoomId,(int)directionCode) from dlgRoomExit::save() creates additional entries in TRoom::entranceMap even for non-exit directions. To reduce (but unfortunately not eliminate) the number of duplicates change the save() code to only use setExit() when a difference between the current and saved exit room numbers is found. Commit 06 of 10 originally entitled: "Fixup: clear TRoomDB::entranceMap on map clearance" Obvious but was missing. Commit 07 of 10 originally entitled: "Fixup: add getAllRoomEntrances() to Lua command set" Though suitable for release code this was added to help with debugging. This was what enabled me to spot the problems that the previous pair of commits ameliorates. This currently only reports the rooms that have exit(s) that lead to the given room Id. It is anticipated that there will be a future revision to report the particular direction(s) from the given room(s) are the one(s) that lead to the room, using a second argument that will be a boolean true to trigger that behavior (the absence of, or a false, second argument would then cause the result that this code produces.) Conflicts resolved in: src/TLuaInterpreter.cpp src/TLuaInterpreter.h Commit 08 of 10 originally entitled: "Fixup: add debugging output to TRoomDB::updateEntranceMap(TRoom *)" Set a break point in the method and change the static bool showDebug to dis-/en-able output... Conflicts resolved in: src/TRoomDB.cpp Commit 09 of 10 originally entitled: "FixEnhance: fix entranceMap maintenance, bulk room deletion & map loading" Previously we were not removing entries from the entranceMap involving the value (a room that the room Id that was a key had an entrance FROM) when a route was changed. There is a performance cost in ensuring the data is kept correctly - there may be a modest gain by storing the entrance data within each TRoom class instance rather than a central database in TRoomDB... Deletion of multiple rooms and map loading can be done more efficiently if we skip some redundant steps. Also added/revised some timing code to measure things. Conflicts resolved in: src/TRoomDB.cpp src/TRoomDB.h Commit 10 of 10 originally entitled: "BugFix: Some previous coding errors" * T2DMap::slot_setArea(): used a uint where I should have used an int as a method I called can return a -1 in some cases. * TArea::getAreaExitRoomData(): a qWarning() in a debugging line I had used the wrong type (%1,%2,...) of format string argument characters when I should of used (%i or %s)... * (bool)TArea::mIsDirty: was put in wrong block of lines in header Conflicts resolved in: src/TArea.h Further conflicts resolved which were brought about by later re-basing before posting code out to world: src/dlgRoomExits.cpp Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-08-15 22:15:39 +01:00
// FIXME: This along with TRoom->setExit need to be unified to a controller.
TRoom* pR = mpRoomDB->getRoom(from);
TRoom* pR_to = mpRoomDB->getRoom(to);
2013-03-22 12:47:58 +01:00
if (!pR) {
Revise: massage Area Exit data to required format and ensure it is correct Rename: (void)TArea::fast_ausgaengeBestimmen(int) ==> TArea::determineAreaExitsOfRoom (void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits (const)(QList<int>)TArea::getAreaExits() const ==> TArea::getAreaExitRoomIds() Add new method to return area exit data in new, wanted format: (const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const In preparation to revising internal storage representation of area exit data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member from public to private area of class. To permit save and load the following have had to be made friends of the TArea class: (bool)TMap::serialize( QDataStream & ) and (bool)TMap::restore( QString ) Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on current and all previous map file format versions, will not be needed on future version as the code to manage the areaExits data is now functional. Previous code would have done this only for versions prior to 14 files (current is 16) or if the lua function auditAreas() was manually run. In passing also modified code that "fixed-up" "old style" map labels so that it is no longer run on current version files and pushes any messages that that creates into the main profile console instead of using standard C++ cout calls which we deprecate now. All code blocks that have been touched by this series of commits have been re-formatted to current styles. Update copyrights on all files touched that have not already been marked as having been edited by myself. Revised TLuaInterpreter::getAreaExits(...) to take a second optional Boolean that if present and true cause it to return data about the area exit directions and the destination rooms, if false or omitted, returns only the rooms in the area that have exits out of it, reproducing the previous implementation. In either case the result is a table if there are area exits (or a nil for an isolate area without exits); two additional values are returned an informative, translatable, text message and an integer status code that reflects the same information. When moving a series of rooms to a different area via the 2D mapper's GUI the recalculations for the area extremes {by TArea::calcSpan()} and the out of area exits {by TArea::determineAreaExits()} can now be deferred until the last room has been moved by passing a third true (boolean) argument to TMap::setRoomArea(...) which defaults to false for other single room at a time usages. Though that method keeps a local copy of the areas that have been modified and thus need updating, should the last room NOT be processed (null TRooo pointer for room Id) a publicly accessible "mIsDirty" flag is also used so that recovery code can identify and clean up those affected areas otherwise. It is possible that this flag may be useful in other situations, such as when moving or adding multiple rooms WITHIN an area. *** This commit has been rebased so it's history might not be the same as someone else's copy of it *** Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-05 01:20:15 +00:00
return false;
}
if (!pR_to && to > 0) {
Revise: massage Area Exit data to required format and ensure it is correct Rename: (void)TArea::fast_ausgaengeBestimmen(int) ==> TArea::determineAreaExitsOfRoom (void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits (const)(QList<int>)TArea::getAreaExits() const ==> TArea::getAreaExitRoomIds() Add new method to return area exit data in new, wanted format: (const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const In preparation to revising internal storage representation of area exit data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member from public to private area of class. To permit save and load the following have had to be made friends of the TArea class: (bool)TMap::serialize( QDataStream & ) and (bool)TMap::restore( QString ) Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on current and all previous map file format versions, will not be needed on future version as the code to manage the areaExits data is now functional. Previous code would have done this only for versions prior to 14 files (current is 16) or if the lua function auditAreas() was manually run. In passing also modified code that "fixed-up" "old style" map labels so that it is no longer run on current version files and pushes any messages that that creates into the main profile console instead of using standard C++ cout calls which we deprecate now. All code blocks that have been touched by this series of commits have been re-formatted to current styles. Update copyrights on all files touched that have not already been marked as having been edited by myself. Revised TLuaInterpreter::getAreaExits(...) to take a second optional Boolean that if present and true cause it to return data about the area exit directions and the destination rooms, if false or omitted, returns only the rooms in the area that have exits out of it, reproducing the previous implementation. In either case the result is a table if there are area exits (or a nil for an isolate area without exits); two additional values are returned an informative, translatable, text message and an integer status code that reflects the same information. When moving a series of rooms to a different area via the 2D mapper's GUI the recalculations for the area extremes {by TArea::calcSpan()} and the out of area exits {by TArea::determineAreaExits()} can now be deferred until the last room has been moved by passing a third true (boolean) argument to TMap::setRoomArea(...) which defaults to false for other single room at a time usages. Though that method keeps a local copy of the areas that have been modified and thus need updating, should the last room NOT be processed (null TRooo pointer for room Id) a publicly accessible "mIsDirty" flag is also used so that recovery code can identify and clean up those affected areas otherwise. It is possible that this flag may be useful in other situations, such as when moving or adding multiple rooms WITHIN an area. *** This commit has been rebased so it's history might not be the same as someone else's copy of it *** Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-05 01:20:15 +00:00
return false;
}
if (to < 1) {
Revise: massage Area Exit data to required format and ensure it is correct Rename: (void)TArea::fast_ausgaengeBestimmen(int) ==> TArea::determineAreaExitsOfRoom (void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits (const)(QList<int>)TArea::getAreaExits() const ==> TArea::getAreaExitRoomIds() Add new method to return area exit data in new, wanted format: (const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const In preparation to revising internal storage representation of area exit data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member from public to private area of class. To permit save and load the following have had to be made friends of the TArea class: (bool)TMap::serialize( QDataStream & ) and (bool)TMap::restore( QString ) Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on current and all previous map file format versions, will not be needed on future version as the code to manage the areaExits data is now functional. Previous code would have done this only for versions prior to 14 files (current is 16) or if the lua function auditAreas() was manually run. In passing also modified code that "fixed-up" "old style" map labels so that it is no longer run on current version files and pushes any messages that that creates into the main profile console instead of using standard C++ cout calls which we deprecate now. All code blocks that have been touched by this series of commits have been re-formatted to current styles. Update copyrights on all files touched that have not already been marked as having been edited by myself. Revised TLuaInterpreter::getAreaExits(...) to take a second optional Boolean that if present and true cause it to return data about the area exit directions and the destination rooms, if false or omitted, returns only the rooms in the area that have exits out of it, reproducing the previous implementation. In either case the result is a table if there are area exits (or a nil for an isolate area without exits); two additional values are returned an informative, translatable, text message and an integer status code that reflects the same information. When moving a series of rooms to a different area via the 2D mapper's GUI the recalculations for the area extremes {by TArea::calcSpan()} and the out of area exits {by TArea::determineAreaExits()} can now be deferred until the last room has been moved by passing a third true (boolean) argument to TMap::setRoomArea(...) which defaults to false for other single room at a time usages. Though that method keeps a local copy of the areas that have been modified and thus need updating, should the last room NOT be processed (null TRooo pointer for room Id) a publicly accessible "mIsDirty" flag is also used so that recovery code can identify and clean up those affected areas otherwise. It is possible that this flag may be useful in other situations, such as when moving or adding multiple rooms WITHIN an area. *** This commit has been rebased so it's history might not be the same as someone else's copy of it *** Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-05 01:20:15 +00:00
to = -1;
}
2010-12-28 23:31:03 +01:00
2013-05-26 11:47:15 +02:00
bool ret = true;
2010-09-07 20:35:32 +02:00
switch (dir) {
case DIR_NORTH:
pR->setNorth(to);
break;
case DIR_NORTHEAST:
pR->setNortheast(to);
break;
case DIR_NORTHWEST:
pR->setNorthwest(to);
break;
case DIR_EAST:
pR->setEast(to);
break;
case DIR_WEST:
pR->setWest(to);
break;
case DIR_SOUTH:
pR->setSouth(to);
break;
case DIR_SOUTHEAST:
pR->setSoutheast(to);
break;
case DIR_SOUTHWEST:
pR->setSouthwest(to);
break;
case DIR_UP:
pR->setUp(to);
break;
case DIR_DOWN:
pR->setDown(to);
break;
case DIR_IN:
pR->setIn(to);
break;
case DIR_OUT:
pR->setOut(to);
break;
default:
ret = false;
2010-09-07 20:35:32 +02:00
}
Enhancement: Improved/extended exits GUI for 2D mapper The GUI formed by dlgRoomExits.{cpp|h} and room_exits.ui combined now provide full control and aim to enforce relational consistency between the data items that provide all the exits from a particular room. All controls should have tool-tips - some context sensitive and provide support for some aspects that are not yet implemented in other parts of the code e.g. door markers for the mapper on exits not in the XY-Plane. As the controls for each normal exit are duplicated, labels are not given for the individual components to save space, instead an expanded disabled dummy with labels is provided as a Key. Unfortunately even after this the dialogue is still a little large and it has been suggested to replace the four radio buttons that provide control over the door item with a combo-box with the four fixed values... Following support methods have been changed/added: bool TRoom::hasExitStub(int) - modified, to provide a Boolean type result consistent with functionality. void TRoom::setExitStub(int, bool) - modified, remove ALL existing stub entries for the given direction code if the second argument is false, only adds a new entry if a corresponding one was not present - this is required for the data storage type (QList) for stubs which could otherwise take multiple entries for the same key (exit). Changed second argument to Boolean type to reflect its functionality. bool TRoom::hasExitWeight(QString) - new, needed for the GUI to determine source of weight data for exit. Normally that detail is hidden from consumers of this data. void TRoom::setExitWeight(QString, int) - modified, to permit it to remove data item for an exit. Uses zero or negative weight value which additionally aides route-finding code that consumes this data but requires only positive weight data. Removal of specific exit weight data permits reversion to use of overall weight value set in ROOM's weight. void TRoom::setDoor(QString, int) - new, implemented previously declared but not defined code. First argument as lower case initials for normal exits in XY-plane and "up", "down", "in", "out" for other normal exits. Supports special exits though no support at this point in 2D mapper for these or non-XY-plane exits. Second argument is door type (0=none, 1=open, 2=closed, 3=locked) and value of 0 will remove instance data of any of the other type. int TRoom::getDoor(QString) - new, companion to setDoor, uses same first argument to determine exit to return door code of. Returns zero for any exit specified which does not have a door explicitly set. Note: Parts of code-base still access door data directly at this point, further work required before that data could be made private to TRoom class. void TRoom::setArea(int) - modified, warning for room not having valid previous area enabled. bool TRoom::hasExit(int) - modified, method not being in use, re-purposed to use to test for an actual exit in given normal exit direction. Test used is simple, fast and may produce false positives (checks only for exit to room Id NOT being -1). A more thorough check would be to check that mpRoomDB->getRoom( exitId ) != 0 where exitId is value already determined not to be -1. bool TRoom::setExit(int, int) - new, uses a direction code as a first argument to set the exit to the exitId given as second. Intended to replace individual setNorth()...setOut() series of methods in cases requiring iteration through all normal exits. int TRoom::getExit(int) - new, companion to the new setExit(). bool TRoom::setSpecialExitLock(QString, bool) - new, substitute for other version which does not need to have the destination room supplied. Unlike the void method it supplants, it provides a bool return, true on success. void TRoom::setSpecialExit(int, QString) - replacement for addSpecialExit() renamed because now capable of removing a special exit if the first argument, the exit to room Id is less than one. Lua command removeSpecialExit( fromRoomId, cmd ) with no normal return value added for users' use, eliminating the need to remove all exits and re-adding all others in order to remove or change just one. Corresponding addSpecialExit( fromRoomId, toRoomId, cmd ) now able to change the toRoomId for an existing exit "cmd" from given fromRoomId room. void TRoom::removeAllSpecialExitsToRoom(int) - modified, now ensures the corresponding TArea::exits is updated upon removal of all the special exits from a room. void TRoom::auditExits() - modified, missing checks added for up and down normal exits, and reporting for all normal exits. Code restructured to avoid use of two "goto" commands and consequent restarts in checking of special exits if they were to be executed. int TRoomDB::getArea(TArea *) - commented out prior to removal, it is mis-named as it returned an integer area Id not a TArea value, pointer or reference. Also it's given functionality is already provided by int TRoomDB::getAreaID(TArea *) and the implied action by TArea * TRoomDB::getArea(int). Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2014-03-15 05:16:30 +00:00
pR->setExitStub(dir, false);
mMapGraphNeedsUpdate = true;
TArea* pA = mpRoomDB->getArea(pR->getArea());
if (!pA) {
return false;
Revise: massage Area Exit data to required format and ensure it is correct Rename: (void)TArea::fast_ausgaengeBestimmen(int) ==> TArea::determineAreaExitsOfRoom (void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits (const)(QList<int>)TArea::getAreaExits() const ==> TArea::getAreaExitRoomIds() Add new method to return area exit data in new, wanted format: (const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const In preparation to revising internal storage representation of area exit data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member from public to private area of class. To permit save and load the following have had to be made friends of the TArea class: (bool)TMap::serialize( QDataStream & ) and (bool)TMap::restore( QString ) Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on current and all previous map file format versions, will not be needed on future version as the code to manage the areaExits data is now functional. Previous code would have done this only for versions prior to 14 files (current is 16) or if the lua function auditAreas() was manually run. In passing also modified code that "fixed-up" "old style" map labels so that it is no longer run on current version files and pushes any messages that that creates into the main profile console instead of using standard C++ cout calls which we deprecate now. All code blocks that have been touched by this series of commits have been re-formatted to current styles. Update copyrights on all files touched that have not already been marked as having been edited by myself. Revised TLuaInterpreter::getAreaExits(...) to take a second optional Boolean that if present and true cause it to return data about the area exit directions and the destination rooms, if false or omitted, returns only the rooms in the area that have exits out of it, reproducing the previous implementation. In either case the result is a table if there are area exits (or a nil for an isolate area without exits); two additional values are returned an informative, translatable, text message and an integer status code that reflects the same information. When moving a series of rooms to a different area via the 2D mapper's GUI the recalculations for the area extremes {by TArea::calcSpan()} and the out of area exits {by TArea::determineAreaExits()} can now be deferred until the last room has been moved by passing a third true (boolean) argument to TMap::setRoomArea(...) which defaults to false for other single room at a time usages. Though that method keeps a local copy of the areas that have been modified and thus need updating, should the last room NOT be processed (null TRooo pointer for room Id) a publicly accessible "mIsDirty" flag is also used so that recovery code can identify and clean up those affected areas otherwise. It is possible that this flag may be useful in other situations, such as when moving or adding multiple rooms WITHIN an area. *** This commit has been rebased so it's history might not be the same as someone else's copy of it *** Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-05 01:20:15 +00:00
}
pA->determineAreaExitsOfRoom(pR->getId());
Backport: merge ten commits room "entrance" code from "release_30" to "development" branches, Commit 01 of 10 originally entitled: "fix for keeping reverse area exit map in sync with exit creation, adding, and deletion" Conflicts resolved in: src/TRoom.h Commit 02 of 10 originally entitled: "bug fix for entranceMap having reversed key and value" Conflicts resolved in: src/TRoomDB.cpp Commit 03 of 10 originally entitled: "removal of entranceMap cleanup" Conflicts resolved in: src/TRoomDB.cpp Commit 04 of 10 originally entitled: "BugFix: prevent crash in dlgRoomExits::initExits() on missing exit" Code deficiencies that remove rooms without properly updating connected rooms were causing segmentation faults because this method - perhaps foolishly - expected a room to exist when another room had an exit Id to the room given. This commit corrects any faulty normal exits now by resetting them to the no exit -1 value. Commit 05 of 10 originally entitled: "Fixup: prevent unneeded TRoom::setExit() calls from dlgRoomExits class" Each individual call to TRoom::setExit((int)exitRoomId,(int)directionCode) from dlgRoomExit::save() creates additional entries in TRoom::entranceMap even for non-exit directions. To reduce (but unfortunately not eliminate) the number of duplicates change the save() code to only use setExit() when a difference between the current and saved exit room numbers is found. Commit 06 of 10 originally entitled: "Fixup: clear TRoomDB::entranceMap on map clearance" Obvious but was missing. Commit 07 of 10 originally entitled: "Fixup: add getAllRoomEntrances() to Lua command set" Though suitable for release code this was added to help with debugging. This was what enabled me to spot the problems that the previous pair of commits ameliorates. This currently only reports the rooms that have exit(s) that lead to the given room Id. It is anticipated that there will be a future revision to report the particular direction(s) from the given room(s) are the one(s) that lead to the room, using a second argument that will be a boolean true to trigger that behavior (the absence of, or a false, second argument would then cause the result that this code produces.) Conflicts resolved in: src/TLuaInterpreter.cpp src/TLuaInterpreter.h Commit 08 of 10 originally entitled: "Fixup: add debugging output to TRoomDB::updateEntranceMap(TRoom *)" Set a break point in the method and change the static bool showDebug to dis-/en-able output... Conflicts resolved in: src/TRoomDB.cpp Commit 09 of 10 originally entitled: "FixEnhance: fix entranceMap maintenance, bulk room deletion & map loading" Previously we were not removing entries from the entranceMap involving the value (a room that the room Id that was a key had an entrance FROM) when a route was changed. There is a performance cost in ensuring the data is kept correctly - there may be a modest gain by storing the entrance data within each TRoom class instance rather than a central database in TRoomDB... Deletion of multiple rooms and map loading can be done more efficiently if we skip some redundant steps. Also added/revised some timing code to measure things. Conflicts resolved in: src/TRoomDB.cpp src/TRoomDB.h Commit 10 of 10 originally entitled: "BugFix: Some previous coding errors" * T2DMap::slot_setArea(): used a uint where I should have used an int as a method I called can return a -1 in some cases. * TArea::getAreaExitRoomData(): a qWarning() in a debugging line I had used the wrong type (%1,%2,...) of format string argument characters when I should of used (%i or %s)... * (bool)TArea::mIsDirty: was put in wrong block of lines in header Conflicts resolved in: src/TArea.h Further conflicts resolved which were brought about by later re-basing before posting code out to world: src/dlgRoomExits.cpp Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-08-15 22:15:39 +01:00
mpRoomDB->updateEntranceMap(pR);
setUnsaved(__func__);
2013-05-26 11:47:15 +02:00
return ret;
2010-09-07 20:35:32 +02:00
}
void TMap::audit()
2010-08-25 00:41:43 +02:00
{
// init areas
Backport: merge ten commits room "entrance" code from "release_30" to "development" branches, Commit 01 of 10 originally entitled: "fix for keeping reverse area exit map in sync with exit creation, adding, and deletion" Conflicts resolved in: src/TRoom.h Commit 02 of 10 originally entitled: "bug fix for entranceMap having reversed key and value" Conflicts resolved in: src/TRoomDB.cpp Commit 03 of 10 originally entitled: "removal of entranceMap cleanup" Conflicts resolved in: src/TRoomDB.cpp Commit 04 of 10 originally entitled: "BugFix: prevent crash in dlgRoomExits::initExits() on missing exit" Code deficiencies that remove rooms without properly updating connected rooms were causing segmentation faults because this method - perhaps foolishly - expected a room to exist when another room had an exit Id to the room given. This commit corrects any faulty normal exits now by resetting them to the no exit -1 value. Commit 05 of 10 originally entitled: "Fixup: prevent unneeded TRoom::setExit() calls from dlgRoomExits class" Each individual call to TRoom::setExit((int)exitRoomId,(int)directionCode) from dlgRoomExit::save() creates additional entries in TRoom::entranceMap even for non-exit directions. To reduce (but unfortunately not eliminate) the number of duplicates change the save() code to only use setExit() when a difference between the current and saved exit room numbers is found. Commit 06 of 10 originally entitled: "Fixup: clear TRoomDB::entranceMap on map clearance" Obvious but was missing. Commit 07 of 10 originally entitled: "Fixup: add getAllRoomEntrances() to Lua command set" Though suitable for release code this was added to help with debugging. This was what enabled me to spot the problems that the previous pair of commits ameliorates. This currently only reports the rooms that have exit(s) that lead to the given room Id. It is anticipated that there will be a future revision to report the particular direction(s) from the given room(s) are the one(s) that lead to the room, using a second argument that will be a boolean true to trigger that behavior (the absence of, or a false, second argument would then cause the result that this code produces.) Conflicts resolved in: src/TLuaInterpreter.cpp src/TLuaInterpreter.h Commit 08 of 10 originally entitled: "Fixup: add debugging output to TRoomDB::updateEntranceMap(TRoom *)" Set a break point in the method and change the static bool showDebug to dis-/en-able output... Conflicts resolved in: src/TRoomDB.cpp Commit 09 of 10 originally entitled: "FixEnhance: fix entranceMap maintenance, bulk room deletion & map loading" Previously we were not removing entries from the entranceMap involving the value (a room that the room Id that was a key had an entrance FROM) when a route was changed. There is a performance cost in ensuring the data is kept correctly - there may be a modest gain by storing the entrance data within each TRoom class instance rather than a central database in TRoomDB... Deletion of multiple rooms and map loading can be done more efficiently if we skip some redundant steps. Also added/revised some timing code to measure things. Conflicts resolved in: src/TRoomDB.cpp src/TRoomDB.h Commit 10 of 10 originally entitled: "BugFix: Some previous coding errors" * T2DMap::slot_setArea(): used a uint where I should have used an int as a method I called can return a -1 in some cases. * TArea::getAreaExitRoomData(): a qWarning() in a debugging line I had used the wrong type (%1,%2,...) of format string argument characters when I should of used (%i or %s)... * (bool)TArea::mIsDirty: was put in wrong block of lines in header Conflicts resolved in: src/TArea.h Further conflicts resolved which were brought about by later re-basing before posting code out to world: src/dlgRoomExits.cpp Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-08-15 22:15:39 +01:00
QElapsedTimer _time;
Revise: massage Area Exit data to required format and ensure it is correct Rename: (void)TArea::fast_ausgaengeBestimmen(int) ==> TArea::determineAreaExitsOfRoom (void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits (const)(QList<int>)TArea::getAreaExits() const ==> TArea::getAreaExitRoomIds() Add new method to return area exit data in new, wanted format: (const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const In preparation to revising internal storage representation of area exit data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member from public to private area of class. To permit save and load the following have had to be made friends of the TArea class: (bool)TMap::serialize( QDataStream & ) and (bool)TMap::restore( QString ) Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on current and all previous map file format versions, will not be needed on future version as the code to manage the areaExits data is now functional. Previous code would have done this only for versions prior to 14 files (current is 16) or if the lua function auditAreas() was manually run. In passing also modified code that "fixed-up" "old style" map labels so that it is no longer run on current version files and pushes any messages that that creates into the main profile console instead of using standard C++ cout calls which we deprecate now. All code blocks that have been touched by this series of commits have been re-formatted to current styles. Update copyrights on all files touched that have not already been marked as having been edited by myself. Revised TLuaInterpreter::getAreaExits(...) to take a second optional Boolean that if present and true cause it to return data about the area exit directions and the destination rooms, if false or omitted, returns only the rooms in the area that have exits out of it, reproducing the previous implementation. In either case the result is a table if there are area exits (or a nil for an isolate area without exits); two additional values are returned an informative, translatable, text message and an integer status code that reflects the same information. When moving a series of rooms to a different area via the 2D mapper's GUI the recalculations for the area extremes {by TArea::calcSpan()} and the out of area exits {by TArea::determineAreaExits()} can now be deferred until the last room has been moved by passing a third true (boolean) argument to TMap::setRoomArea(...) which defaults to false for other single room at a time usages. Though that method keeps a local copy of the areas that have been modified and thus need updating, should the last room NOT be processed (null TRooo pointer for room Id) a publicly accessible "mIsDirty" flag is also used so that recovery code can identify and clean up those affected areas otherwise. It is possible that this flag may be useful in other situations, such as when moving or adding multiple rooms WITHIN an area. *** This commit has been rebased so it's history might not be the same as someone else's copy of it *** Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-05 01:20:15 +00:00
_time.start();
{ // Blocked - just to limit the scope of infoMsg...!
const QString infoMsg = tr("[ INFO ] - Map audit starting...");
postMessage(infoMsg);
Revise: massage Area Exit data to required format and ensure it is correct Rename: (void)TArea::fast_ausgaengeBestimmen(int) ==> TArea::determineAreaExitsOfRoom (void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits (const)(QList<int>)TArea::getAreaExits() const ==> TArea::getAreaExitRoomIds() Add new method to return area exit data in new, wanted format: (const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const In preparation to revising internal storage representation of area exit data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member from public to private area of class. To permit save and load the following have had to be made friends of the TArea class: (bool)TMap::serialize( QDataStream & ) and (bool)TMap::restore( QString ) Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on current and all previous map file format versions, will not be needed on future version as the code to manage the areaExits data is now functional. Previous code would have done this only for versions prior to 14 files (current is 16) or if the lua function auditAreas() was manually run. In passing also modified code that "fixed-up" "old style" map labels so that it is no longer run on current version files and pushes any messages that that creates into the main profile console instead of using standard C++ cout calls which we deprecate now. All code blocks that have been touched by this series of commits have been re-formatted to current styles. Update copyrights on all files touched that have not already been marked as having been edited by myself. Revised TLuaInterpreter::getAreaExits(...) to take a second optional Boolean that if present and true cause it to return data about the area exit directions and the destination rooms, if false or omitted, returns only the rooms in the area that have exits out of it, reproducing the previous implementation. In either case the result is a table if there are area exits (or a nil for an isolate area without exits); two additional values are returned an informative, translatable, text message and an integer status code that reflects the same information. When moving a series of rooms to a different area via the 2D mapper's GUI the recalculations for the area extremes {by TArea::calcSpan()} and the out of area exits {by TArea::determineAreaExits()} can now be deferred until the last room has been moved by passing a third true (boolean) argument to TMap::setRoomArea(...) which defaults to false for other single room at a time usages. Though that method keeps a local copy of the areas that have been modified and thus need updating, should the last room NOT be processed (null TRooo pointer for room Id) a publicly accessible "mIsDirty" flag is also used so that recovery code can identify and clean up those affected areas otherwise. It is possible that this flag may be useful in other situations, such as when moving or adding multiple rooms WITHIN an area. *** This commit has been rebased so it's history might not be the same as someone else's copy of it *** Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-05 01:20:15 +00:00
}
// The old mpRoomDB->initAreasForOldMaps() was a subset of these checks
QHash<int, int> roomRemapping; // These are populated by the auditRooms(...)
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
QHash<int, int> areaRemapping; // call and contain "Keys" of old ids and
// "Values" of new ids to use in their stead
Revise: massage Area Exit data to required format and ensure it is correct Rename: (void)TArea::fast_ausgaengeBestimmen(int) ==> TArea::determineAreaExitsOfRoom (void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits (const)(QList<int>)TArea::getAreaExits() const ==> TArea::getAreaExitRoomIds() Add new method to return area exit data in new, wanted format: (const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const In preparation to revising internal storage representation of area exit data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member from public to private area of class. To permit save and load the following have had to be made friends of the TArea class: (bool)TMap::serialize( QDataStream & ) and (bool)TMap::restore( QString ) Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on current and all previous map file format versions, will not be needed on future version as the code to manage the areaExits data is now functional. Previous code would have done this only for versions prior to 14 files (current is 16) or if the lua function auditAreas() was manually run. In passing also modified code that "fixed-up" "old style" map labels so that it is no longer run on current version files and pushes any messages that that creates into the main profile console instead of using standard C++ cout calls which we deprecate now. All code blocks that have been touched by this series of commits have been re-formatted to current styles. Update copyrights on all files touched that have not already been marked as having been edited by myself. Revised TLuaInterpreter::getAreaExits(...) to take a second optional Boolean that if present and true cause it to return data about the area exit directions and the destination rooms, if false or omitted, returns only the rooms in the area that have exits out of it, reproducing the previous implementation. In either case the result is a table if there are area exits (or a nil for an isolate area without exits); two additional values are returned an informative, translatable, text message and an integer status code that reflects the same information. When moving a series of rooms to a different area via the 2D mapper's GUI the recalculations for the area extremes {by TArea::calcSpan()} and the out of area exits {by TArea::determineAreaExits()} can now be deferred until the last room has been moved by passing a third true (boolean) argument to TMap::setRoomArea(...) which defaults to false for other single room at a time usages. Though that method keeps a local copy of the areas that have been modified and thus need updating, should the last room NOT be processed (null TRooo pointer for room Id) a publicly accessible "mIsDirty" flag is also used so that recovery code can identify and clean up those affected areas otherwise. It is possible that this flag may be useful in other situations, such as when moving or adding multiple rooms WITHIN an area. *** This commit has been rebased so it's history might not be the same as someone else's copy of it *** Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-05 01:20:15 +00:00
if (mVersion < 16) {
Revise: massage Area Exit data to required format and ensure it is correct Rename: (void)TArea::fast_ausgaengeBestimmen(int) ==> TArea::determineAreaExitsOfRoom (void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits (const)(QList<int>)TArea::getAreaExits() const ==> TArea::getAreaExitRoomIds() Add new method to return area exit data in new, wanted format: (const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const In preparation to revising internal storage representation of area exit data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member from public to private area of class. To permit save and load the following have had to be made friends of the TArea class: (bool)TMap::serialize( QDataStream & ) and (bool)TMap::restore( QString ) Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on current and all previous map file format versions, will not be needed on future version as the code to manage the areaExits data is now functional. Previous code would have done this only for versions prior to 14 files (current is 16) or if the lua function auditAreas() was manually run. In passing also modified code that "fixed-up" "old style" map labels so that it is no longer run on current version files and pushes any messages that that creates into the main profile console instead of using standard C++ cout calls which we deprecate now. All code blocks that have been touched by this series of commits have been re-formatted to current styles. Update copyrights on all files touched that have not already been marked as having been edited by myself. Revised TLuaInterpreter::getAreaExits(...) to take a second optional Boolean that if present and true cause it to return data about the area exit directions and the destination rooms, if false or omitted, returns only the rooms in the area that have exits out of it, reproducing the previous implementation. In either case the result is a table if there are area exits (or a nil for an isolate area without exits); two additional values are returned an informative, translatable, text message and an integer status code that reflects the same information. When moving a series of rooms to a different area via the 2D mapper's GUI the recalculations for the area extremes {by TArea::calcSpan()} and the out of area exits {by TArea::determineAreaExits()} can now be deferred until the last room has been moved by passing a third true (boolean) argument to TMap::setRoomArea(...) which defaults to false for other single room at a time usages. Though that method keeps a local copy of the areas that have been modified and thus need updating, should the last room NOT be processed (null TRooo pointer for room Id) a publicly accessible "mIsDirty" flag is also used so that recovery code can identify and clean up those affected areas otherwise. It is possible that this flag may be useful in other situations, such as when moving or adding multiple rooms WITHIN an area. *** This commit has been rebased so it's history might not be the same as someone else's copy of it *** Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-05 01:20:15 +00:00
// convert old style labels, wasn't made version conditional in past but
// not likely to be an issue in recent map file format versions (say 16+)
QMapIterator<int, TArea*> itArea(mpRoomDB->getAreaMap());
while (itArea.hasNext()) {
Revise: massage Area Exit data to required format and ensure it is correct Rename: (void)TArea::fast_ausgaengeBestimmen(int) ==> TArea::determineAreaExitsOfRoom (void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits (const)(QList<int>)TArea::getAreaExits() const ==> TArea::getAreaExitRoomIds() Add new method to return area exit data in new, wanted format: (const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const In preparation to revising internal storage representation of area exit data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member from public to private area of class. To permit save and load the following have had to be made friends of the TArea class: (bool)TMap::serialize( QDataStream & ) and (bool)TMap::restore( QString ) Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on current and all previous map file format versions, will not be needed on future version as the code to manage the areaExits data is now functional. Previous code would have done this only for versions prior to 14 files (current is 16) or if the lua function auditAreas() was manually run. In passing also modified code that "fixed-up" "old style" map labels so that it is no longer run on current version files and pushes any messages that that creates into the main profile console instead of using standard C++ cout calls which we deprecate now. All code blocks that have been touched by this series of commits have been re-formatted to current styles. Update copyrights on all files touched that have not already been marked as having been edited by myself. Revised TLuaInterpreter::getAreaExits(...) to take a second optional Boolean that if present and true cause it to return data about the area exit directions and the destination rooms, if false or omitted, returns only the rooms in the area that have exits out of it, reproducing the previous implementation. In either case the result is a table if there are area exits (or a nil for an isolate area without exits); two additional values are returned an informative, translatable, text message and an integer status code that reflects the same information. When moving a series of rooms to a different area via the 2D mapper's GUI the recalculations for the area extremes {by TArea::calcSpan()} and the out of area exits {by TArea::determineAreaExits()} can now be deferred until the last room has been moved by passing a third true (boolean) argument to TMap::setRoomArea(...) which defaults to false for other single room at a time usages. Though that method keeps a local copy of the areas that have been modified and thus need updating, should the last room NOT be processed (null TRooo pointer for room Id) a publicly accessible "mIsDirty" flag is also used so that recovery code can identify and clean up those affected areas otherwise. It is possible that this flag may be useful in other situations, such as when moving or adding multiple rooms WITHIN an area. *** This commit has been rebased so it's history might not be the same as someone else's copy of it *** Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-05 01:20:15 +00:00
itArea.next();
const int areaID = itArea.key();
TArea* pArea = mpRoomDB->getArea(areaID);
if (!pArea) {
continue;
}
if (!pArea->mMapLabels.isEmpty()) {
QList<int> const labelIDList = pArea->mMapLabels.keys();
for (const int& i : labelIDList) {
TMapLabel const l = pArea->mMapLabels.value(i);
if (l.pix.isNull()) {
// Note that two of the last three arguments here
// (false, 40.0) are not the defaults (true, 30.0) used
// now:
const int newID = createMapLabel(areaID, l.text, l.pos.x(), l.pos.y(), l.pos.z(), l.fgColor, l.bgColor, true, false, false, 40.0, 50, std::nullopt, l.fgColor);
if (newID > -1) {
if (mudlet::self()->showMapAuditErrors()) {
const QString msg = tr("[ INFO ] - CONVERTING: old style label, areaID:%1 labelID:%2.").arg(areaID).arg(i);
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
postMessage(msg);
}
appendAreaErrorMsg(areaID, tr("[ INFO ] - Converting old style label id: %1.").arg(i));
pArea->mMapLabels[i] = pArea->mMapLabels.take(newID);
} else {
if (mudlet::self()->showMapAuditErrors()) {
const QString msg = tr("[ WARN ] - CONVERTING: cannot convert old style label in area with id: %1, label id is: %2.").arg(areaID).arg(i);
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
postMessage(msg);
}
appendAreaErrorMsg(areaID, tr("[ WARN ] - CONVERTING: cannot convert old style label with id: %1.").arg(i));
Revise: massage Area Exit data to required format and ensure it is correct Rename: (void)TArea::fast_ausgaengeBestimmen(int) ==> TArea::determineAreaExitsOfRoom (void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits (const)(QList<int>)TArea::getAreaExits() const ==> TArea::getAreaExitRoomIds() Add new method to return area exit data in new, wanted format: (const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const In preparation to revising internal storage representation of area exit data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member from public to private area of class. To permit save and load the following have had to be made friends of the TArea class: (bool)TMap::serialize( QDataStream & ) and (bool)TMap::restore( QString ) Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on current and all previous map file format versions, will not be needed on future version as the code to manage the areaExits data is now functional. Previous code would have done this only for versions prior to 14 files (current is 16) or if the lua function auditAreas() was manually run. In passing also modified code that "fixed-up" "old style" map labels so that it is no longer run on current version files and pushes any messages that that creates into the main profile console instead of using standard C++ cout calls which we deprecate now. All code blocks that have been touched by this series of commits have been re-formatted to current styles. Update copyrights on all files touched that have not already been marked as having been edited by myself. Revised TLuaInterpreter::getAreaExits(...) to take a second optional Boolean that if present and true cause it to return data about the area exit directions and the destination rooms, if false or omitted, returns only the rooms in the area that have exits out of it, reproducing the previous implementation. In either case the result is a table if there are area exits (or a nil for an isolate area without exits); two additional values are returned an informative, translatable, text message and an integer status code that reflects the same information. When moving a series of rooms to a different area via the 2D mapper's GUI the recalculations for the area extremes {by TArea::calcSpan()} and the out of area exits {by TArea::determineAreaExits()} can now be deferred until the last room has been moved by passing a third true (boolean) argument to TMap::setRoomArea(...) which defaults to false for other single room at a time usages. Though that method keeps a local copy of the areas that have been modified and thus need updating, should the last room NOT be processed (null TRooo pointer for room Id) a publicly accessible "mIsDirty" flag is also used so that recovery code can identify and clean up those affected areas otherwise. It is possible that this flag may be useful in other situations, such as when moving or adding multiple rooms WITHIN an area. *** This commit has been rebased so it's history might not be the same as someone else's copy of it *** Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-05 01:20:15 +00:00
}
}
if ((l.size.width() > std::numeric_limits<qreal>::max()) || (l.size.width() < -std::numeric_limits<qreal>::max())) {
pArea->mMapLabels[i].size.setWidth(l.pix.width());
Revise: massage Area Exit data to required format and ensure it is correct Rename: (void)TArea::fast_ausgaengeBestimmen(int) ==> TArea::determineAreaExitsOfRoom (void)TArea::ausgaengeBestimmen(int) ==> TArea::determineAreaExits (const)(QList<int>)TArea::getAreaExits() const ==> TArea::getAreaExitRoomIds() Add new method to return area exit data in new, wanted format: (const)(QMultiMap<int, QPair<QString, int> >) getAreaExitRoomData() const In preparation to revising internal storage representation of area exit data moved the: (QMultiMap<int, QPair<int, int> >)(TArea *)->exits member from public to private area of class. To permit save and load the following have had to be made friends of the TArea class: (bool)TMap::serialize( QDataStream & ) and (bool)TMap::restore( QString ) Revise (void)TMap::init(Host *) to run (TArea *)->determineAreaExits() on current and all previous map file format versions, will not be needed on future version as the code to manage the areaExits data is now functional. Previous code would have done this only for versions prior to 14 files (current is 16) or if the lua function auditAreas() was manually run. In passing also modified code that "fixed-up" "old style" map labels so that it is no longer run on current version files and pushes any messages that that creates into the main profile console instead of using standard C++ cout calls which we deprecate now. All code blocks that have been touched by this series of commits have been re-formatted to current styles. Update copyrights on all files touched that have not already been marked as having been edited by myself. Revised TLuaInterpreter::getAreaExits(...) to take a second optional Boolean that if present and true cause it to return data about the area exit directions and the destination rooms, if false or omitted, returns only the rooms in the area that have exits out of it, reproducing the previous implementation. In either case the result is a table if there are area exits (or a nil for an isolate area without exits); two additional values are returned an informative, translatable, text message and an integer status code that reflects the same information. When moving a series of rooms to a different area via the 2D mapper's GUI the recalculations for the area extremes {by TArea::calcSpan()} and the out of area exits {by TArea::determineAreaExits()} can now be deferred until the last room has been moved by passing a third true (boolean) argument to TMap::setRoomArea(...) which defaults to false for other single room at a time usages. Though that method keeps a local copy of the areas that have been modified and thus need updating, should the last room NOT be processed (null TRooo pointer for room Id) a publicly accessible "mIsDirty" flag is also used so that recovery code can identify and clean up those affected areas otherwise. It is possible that this flag may be useful in other situations, such as when moving or adding multiple rooms WITHIN an area. *** This commit has been rebased so it's history might not be the same as someone else's copy of it *** Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-01-05 01:20:15 +00:00
}
if ((l.size.height() > std::numeric_limits<qreal>::max()) || (l.size.height() < -std::numeric_limits<qreal>::max())) {
pArea->mMapLabels[i].size.setHeight(l.pix.height());
2012-12-29 02:16:28 +01:00
}
}
2012-12-29 02:16:28 +01:00
}
}
}
mpRoomDB->auditRooms(roomRemapping, areaRemapping);
// The second half of old mpRoomDB->initAreasForOldMaps() - needed to fixup
// all the (TArea *)->areaExits() that were built wrongly previously,
// calcSpan() may not be required to be done here and now but it is in my
// sights as a target for revision in the future. Slysven
QMapIterator<int, TArea*> itArea(mpRoomDB->getAreaMap());
while (itArea.hasNext()) {
itArea.next();
Infrastructure: make TRoom coordinates private (#7539) #### Summary of PR Changes/Additions Makes the coordinate members of the `TRoom` class private so that access to them can be tracked via methods to set and get them. #### Motivation for Adding to Mudlet This is so that the setters can then subsequently include any extra code that needs to be aware when the room is moved. I intend to improve the detection of rooms being placed in the same position but realised this would be a good preliminary step. #### Additional Information (related issues, discussions, etc.) Removes some dead code setting but not using `(int) quads` and `(int) verts` in `(void) GLWidget::paintGL()` Also using the mouse to drag and thus move selected rooms when those rooms were on different levels would squash them all down to be on the same z-coordinate as the "highlighted centre of the selection" room. This is not as helpful it might seem and instead increased the likelihood of causing room collisions - so now each room will retain it's z coordinate if it is not on the same level as the centre of the multiple room selection. Also move code that likely needs to be run whenever rooms are added/removed/moved within an area to a common block of code (`(void) TArea::clean()`) to help keep things DRY. I intend to put code to update a per area record of rooms that are in the same place within that block in the future - so that the record can be reused without having to be repeatedly recalculated, especially in the paint event for the 2D mapper. --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2024-12-09 14:29:13 +00:00
itArea.value()->clean();
}
{ // Blocked - just to limit the scope of infoMsg...!
const QString infoMsg = tr("[ OK ] - Auditing of map completed (%1s). Enjoy your game...").arg(_time.nsecsElapsed() * 1.0e-9, 0, 'f', 2);
postMessage(infoMsg);
appendErrorMsg(infoMsg);
}
mpHost->getLuaInterpreter()->condenseMapLoad();
2010-08-25 00:41:43 +02:00
}
Infrastructure: make TRoom coordinates private (#7539) #### Summary of PR Changes/Additions Makes the coordinate members of the `TRoom` class private so that access to them can be tracked via methods to set and get them. #### Motivation for Adding to Mudlet This is so that the setters can then subsequently include any extra code that needs to be aware when the room is moved. I intend to improve the detection of rooms being placed in the same position but realised this would be a good preliminary step. #### Additional Information (related issues, discussions, etc.) Removes some dead code setting but not using `(int) quads` and `(int) verts` in `(void) GLWidget::paintGL()` Also using the mouse to drag and thus move selected rooms when those rooms were on different levels would squash them all down to be on the same z-coordinate as the "highlighted centre of the selection" room. This is not as helpful it might seem and instead increased the likelihood of causing room collisions - so now each room will retain it's z coordinate if it is not on the same level as the centre of the multiple room selection. Also move code that likely needs to be run whenever rooms are added/removed/moved within an area to a common block of code (`(void) TArea::clean()`) to help keep things DRY. I intend to put code to update a per area record of rooms that are in the same place within that block in the future - so that the record can be reused without having to be repeatedly recalculated, especially in the paint event for the 2D mapper. --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2024-12-09 14:29:13 +00:00
// This may be duplicating TArea class functionality:
QList<int> TMap::detectRoomCollisions(int id)
2010-12-28 23:31:03 +01:00
{
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
QList<int> collList;
TRoom* pR = mpRoomDB->getRoom(id);
if (!pR) {
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
return collList;
2010-12-28 23:31:03 +01:00
}
const int area = pR->getArea();
Infrastructure: make TRoom coordinates private (#7539) #### Summary of PR Changes/Additions Makes the coordinate members of the `TRoom` class private so that access to them can be tracked via methods to set and get them. #### Motivation for Adding to Mudlet This is so that the setters can then subsequently include any extra code that needs to be aware when the room is moved. I intend to improve the detection of rooms being placed in the same position but realised this would be a good preliminary step. #### Additional Information (related issues, discussions, etc.) Removes some dead code setting but not using `(int) quads` and `(int) verts` in `(void) GLWidget::paintGL()` Also using the mouse to drag and thus move selected rooms when those rooms were on different levels would squash them all down to be on the same z-coordinate as the "highlighted centre of the selection" room. This is not as helpful it might seem and instead increased the likelihood of causing room collisions - so now each room will retain it's z coordinate if it is not on the same level as the centre of the multiple room selection. Also move code that likely needs to be run whenever rooms are added/removed/moved within an area to a common block of code (`(void) TArea::clean()`) to help keep things DRY. I intend to put code to update a per area record of rooms that are in the same place within that block in the future - so that the record can be reused without having to be repeatedly recalculated, especially in the paint event for the 2D mapper. --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2024-12-09 14:29:13 +00:00
const int x = pR->x();
const int y = pR->y();
const int z = pR->z();
TArea* pA = mpRoomDB->getArea(area);
if (!pA) {
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
return collList;
2010-12-28 23:31:03 +01:00
}
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
QSetIterator<int> itRoom(pA->getAreaRooms());
while (itRoom.hasNext()) {
const int checkRoomId = itRoom.next();
pR = mpRoomDB->getRoom(checkRoomId);
if (!pR) {
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
continue;
}
Infrastructure: make TRoom coordinates private (#7539) #### Summary of PR Changes/Additions Makes the coordinate members of the `TRoom` class private so that access to them can be tracked via methods to set and get them. #### Motivation for Adding to Mudlet This is so that the setters can then subsequently include any extra code that needs to be aware when the room is moved. I intend to improve the detection of rooms being placed in the same position but realised this would be a good preliminary step. #### Additional Information (related issues, discussions, etc.) Removes some dead code setting but not using `(int) quads` and `(int) verts` in `(void) GLWidget::paintGL()` Also using the mouse to drag and thus move selected rooms when those rooms were on different levels would squash them all down to be on the same z-coordinate as the "highlighted centre of the selection" room. This is not as helpful it might seem and instead increased the likelihood of causing room collisions - so now each room will retain it's z coordinate if it is not on the same level as the centre of the multiple room selection. Also move code that likely needs to be run whenever rooms are added/removed/moved within an area to a common block of code (`(void) TArea::clean()`) to help keep things DRY. I intend to put code to update a per area record of rooms that are in the same place within that block in the future - so that the record can be reused without having to be repeatedly recalculated, especially in the paint event for the 2D mapper. --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2024-12-09 14:29:13 +00:00
if (pR->x() == x && pR->y() == y && pR->z() == z) {
collList.push_back(checkRoomId);
2010-12-28 23:31:03 +01:00
}
}
return collList;
}
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
// Not used:
//void TMap::astBreitenAnpassung( int id, int id2 )
//{
//}
2010-12-28 23:31:03 +01:00
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
//void TMap::astHoehenAnpassung( int id, int id2 )
//{
//}
2010-12-28 23:31:03 +01:00
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
//void TMap::getConnectedNodesGreaterThanX( int id, int min )
//{
//}
2010-12-28 23:31:03 +01:00
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
//void TMap::getConnectedNodesSmallerThanX( int id, int min )
//{
//}
2010-12-28 23:31:03 +01:00
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
//void TMap::getConnectedNodesGreaterThanY( int id, int min )
//{
//}
2010-12-28 23:31:03 +01:00
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
//void TMap::getConnectedNodesSmallerThanY( int id, int min )
//{
//}
2010-12-28 23:31:03 +01:00
bool TMap::gotoRoom(int r)
2010-08-25 00:41:43 +02:00
{
mTargetID = r;
return findPath(mRoomIdHash.value(mProfileName), r);
2010-08-25 00:41:43 +02:00
}
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
// As can be seen this only sets the target and start point for a path find
// the speedwalk is instigated by the Host class caller...
bool TMap::gotoRoom(int r1, int r2)
2010-08-25 00:41:43 +02:00
{
return findPath(r1, r2);
2010-08-25 00:41:43 +02:00
}
void TMap::addDirectionalRoute(QHash<unsigned int, route>& bestRoutes,
const QMap<QString, int>& exitWeights,
unsigned int source,
TRoom* pSourceR,
int target,
quint8 direction,
const QString& exitKey,
const QSet<unsigned int>& unUsableRoomSet)
{
// Skip self-edges and any exits that lead to rooms already known to be unusable.
if (target <= 0 || static_cast<int>(source) == target) {
return;
}
TLuaInterpreter* interpreter = mpHost ? mpHost->getLuaInterpreter() : nullptr;
TLuaInterpreter::ExitWeightFilterResult filterResult;
TLuaInterpreter::ExitWeightFilterResult* filterResultPtr = nullptr;
if (interpreter && interpreter->hasExitWeightFilter()) {
filterResult = interpreter->applyExitWeightFilter(static_cast<int>(source), exitKey);
if (filterResult.blocked) {
return;
}
filterResultPtr = &filterResult;
}
const bool filterOverridesBlocks = filterResultPtr && filterResultPtr->weightOverride.has_value();
if (pSourceR->isLocked && !filterOverridesBlocks) {
return;
}
const bool isSpecialExit = direction == DIR_OTHER;
if (!filterOverridesBlocks) {
if (isSpecialExit) {
if (pSourceR->hasSpecialExitLock(exitKey)) {
return;
}
} else if (pSourceR->hasExitLock(direction)) {
return;
}
}
TRoom* pTargetR = mpRoomDB->getRoom(target);
if (!pTargetR) {
return;
}
if (!filterOverridesBlocks && (pTargetR->isLocked || unUsableRoomSet.contains(target))) {
return;
}
route r;
r.direction = direction;
if (isSpecialExit) {
r.specialExitName = exitKey;
}
int cost = exitWeights.value(exitKey, pTargetR->getWeight());
if (filterOverridesBlocks) {
cost = filterResultPtr->weightOverride.value();
}
r.cost = cost;
if (!bestRoutes.contains(target) || bestRoutes.value(target).cost > r.cost) {
bestRoutes.insert(target, r);
}
}
void TMap::initGraph()
2010-08-25 00:41:43 +02:00
{
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
QElapsedTimer _time;
_time.start();
2011-07-04 11:50:19 +02:00
locations.clear();
roomidToIndex.clear();
2011-07-04 11:50:19 +02:00
g.clear();
g = mygraph_t();
unsigned int roomCount = 0;
unsigned int edgeCount = 0;
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
QSet<unsigned int> unUsableRoomSet;
TLuaInterpreter* interpreter = mpHost ? mpHost->getLuaInterpreter() : nullptr;
const bool exitWeightFilterActive = interpreter && interpreter->hasExitWeightFilter();
2021-08-22 08:01:05 +02:00
// Keep track of the unusable rather than the usable ones because that is
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
// hopefully a MUCH smaller set in normal situations!
QHashIterator<int, TRoom*> itRoom = mpRoomDB->getRoomMap();
while (itRoom.hasNext()) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
itRoom.next();
TRoom* pR = itRoom.value();
if (itRoom.key() < 1 || !pR) {
unUsableRoomSet.insert(itRoom.key());
continue;
}
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
if (pR->isLocked) {
unUsableRoomSet.insert(itRoom.key());
if (!exitWeightFilterActive) {
continue;
}
}
location l;
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
l.pR = pR;
l.id = itRoom.key();
// locations is std::vector<location> and (locations.at(k)).id will give room ID value
locations.push_back(l);
// This command maps usable TRooms (key) to index of entry in locations (for route finding).
// It loses invalid and unusable (i.e. locked) rooms
roomidToIndex.insert(itRoom.key(), roomCount++);
}
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
for (unsigned int i = 0; i < roomCount; ++i) {
boost::add_vertex(g);
}
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
// Now identify the routes between rooms, and pick out the best edges of parallel ones
for (auto l : locations) {
unsigned const int source = l.id;
TRoom* pSourceR = l.pR;
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
QHash<unsigned int, route> bestRoutes;
// key is target (destination room),
// value is data we will need to store later,
QMap<QString, int> const exitWeights = pSourceR->getExitWeights();
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
addDirectionalRoute(bestRoutes, exitWeights, source, pSourceR, pSourceR->getNorth(), DIR_NORTH, qsl("n"), unUsableRoomSet);
addDirectionalRoute(bestRoutes, exitWeights, source, pSourceR, pSourceR->getEast(), DIR_EAST, qsl("e"), unUsableRoomSet);
addDirectionalRoute(bestRoutes, exitWeights, source, pSourceR, pSourceR->getSouth(), DIR_SOUTH, qsl("s"), unUsableRoomSet);
addDirectionalRoute(bestRoutes, exitWeights, source, pSourceR, pSourceR->getWest(), DIR_WEST, qsl("w"), unUsableRoomSet);
addDirectionalRoute(bestRoutes, exitWeights, source, pSourceR, pSourceR->getUp(), DIR_UP, qsl("up"), unUsableRoomSet);
addDirectionalRoute(bestRoutes, exitWeights, source, pSourceR, pSourceR->getDown(), DIR_DOWN, qsl("down"), unUsableRoomSet);
addDirectionalRoute(bestRoutes, exitWeights, source, pSourceR, pSourceR->getNortheast(), DIR_NORTHEAST, qsl("ne"), unUsableRoomSet);
addDirectionalRoute(bestRoutes, exitWeights, source, pSourceR, pSourceR->getSoutheast(), DIR_SOUTHEAST, qsl("se"), unUsableRoomSet);
addDirectionalRoute(bestRoutes, exitWeights, source, pSourceR, pSourceR->getSouthwest(), DIR_SOUTHWEST, qsl("sw"), unUsableRoomSet);
addDirectionalRoute(bestRoutes, exitWeights, source, pSourceR, pSourceR->getNorthwest(), DIR_NORTHWEST, qsl("nw"), unUsableRoomSet);
addDirectionalRoute(bestRoutes, exitWeights, source, pSourceR, pSourceR->getIn(), DIR_IN, qsl("in"), unUsableRoomSet);
addDirectionalRoute(bestRoutes, exitWeights, source, pSourceR, pSourceR->getOut(), DIR_OUT, qsl("out"), unUsableRoomSet);
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
Refactor: store special exits and their lock status separately (#4526) This will enable some simplification of code. During development it became clear that the Lua API `getSpecialExits(...)` function was a bit defective and did not behave as documented in the Wiki: it was only showing one special exit at random that led to a particular exit room in the (admittedly unlikely) event of there being more than one. It also used the special exit name/command as a key in a sub-table with the special exit lock status of that exit as a "0" or "1" string value. This PR repairs the above function by adding an optional boolean argument that: * if omitted or false, replicates the previous behaviour but if there is more than one special exit to the same room it always picks one with the lowest exit weight that is unlocked or if there is none it picks one with the lowest weight that is locked. This will be compatible with old scripts. * if true, returns ALL the exits in the sub-table that lead to the particular room id that is the key in the main table, again those exit commands are the keys with a value being a "0" or "1" depending on whether the exit is unlocked or locked respectively. For the record, the original implementation of special exits was introduced in commit: e0ba28d4729f97f69cd91b178886ad6e7438d9a9 and that was supported by the addition of map format version 6. Locking of Special Exits was added in somewhere between: 19f8563b47454ca6c625c534384b1c7085351dfc and: 070912ea7c84414be2ddb86c371fc791c5718314 (which revised the map format to 11). Also: * use a couple of `const QString`s as templates in the `dlgRoomExit.cpp` file to remove 95 duplicated `QStringLiterals` from the read-only code segment of the compile object file. * add `const` where relevant to some `TRoom` methods. * work harder to ensure than when a special exit is deleted from a `TRoom` then elements that were related to it are also cleaned up. * prepare to save the new `TRoom` data structures in the next Mudlet map file format (21) when it is enabled. In the meantime a workaround to convert the in-game data to the current format is utilised for all current map formats Mudlet can currently use. This will impact a little on the save/loading speeds but that is the cost of simplifying the code that works with special exits elsewhere in the application. * revise and extend the error handling for the room special exit functions generally so that they confirm to our throwing an error on argument type issue (and reporting the faulty argument) and returning `nil` plus an error message for a run-time value problem. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2020-12-31 22:06:00 +00:00
QMapIterator<QString, int> itSpecialExit(pSourceR->getSpecialExits());
while (itSpecialExit.hasNext()) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
itSpecialExit.next();
addDirectionalRoute(bestRoutes, exitWeights, source, pSourceR, itSpecialExit.value(), DIR_OTHER, itSpecialExit.key(), unUsableRoomSet);
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
} // End of while(itSpecialExit.hasNext())
2021-08-22 08:01:05 +02:00
// Now we have eliminated possible duplicate and useless edges we can create and
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
// insert the remainder into the BGL graph:
QHashIterator<unsigned int, route> itRoute = bestRoutes;
while (itRoute.hasNext()) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
itRoute.next();
edge_descriptor e;
bool inserted; // This is always going to be false as it gets set if
// we had tried to insert a parallel edge into a graph
// that does not support them - but we've just been
// and disposed of those already!
tie(e, inserted) = add_edge(roomidToIndex.value(source), roomidToIndex.value(itRoute.key()), itRoute.value().cost, g);
edgeHash.insert(qMakePair(source, itRoute.key()), itRoute.value());
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
// The key is made from the QPair<edgeSourceRoomId, edgeTargetRoomId>...
edgeCount++;
}
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
} // End of foreach(location l, locations)
mMapGraphNeedsUpdate = false;
qDebug() << "TMap::initGraph() INFO: built graph with:" << locations.size() << "(" << roomCount << ") locations(roomCount), and discarded" << unUsableRoomSet.count()
2021-08-22 08:01:05 +02:00
<< "other NOT usable rooms and found:" << edgeCount << "distinct, usable edges in:" << _time.nsecsElapsed() * 1.0e-6 << "ms.";
}
bool TMap::findPath(int from, int to)
{
if (mMapGraphNeedsUpdate) {
initGraph();
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
}
QElapsedTimer t;
t.start();
mPathList.clear();
mDirList.clear();
mWeightList.clear();
// Clear the previous path data here so that if the following test is
// passed, the data is empty - and valid for THAT case!
if (from == to) {
2021-08-22 08:01:05 +02:00
return true; // Take a short-cut for trivial "already there" case!
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
}
TRoom* pFrom = mpRoomDB->getRoom(from);
TRoom* pTo = mpRoomDB->getRoom(to);
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
if (!pFrom || !pTo) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
qDebug() << "TMap::findPath(" << from << "," << to << ") FAIL: NULL TRoom pointer for start or target rooms!";
return false;
}
bool hasUsableExit = false;
if (pFrom->getNorth() > 0 && (!pFrom->hasExitLock(DIR_NORTH))) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
hasUsableExit = true;
}
if (!hasUsableExit && pFrom->getSouth() > 0 && (!pFrom->hasExitLock(DIR_SOUTH))) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
hasUsableExit = true;
}
if (!hasUsableExit && pFrom->getWest() > 0 && (!pFrom->hasExitLock(DIR_WEST))) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
hasUsableExit = true;
}
if (!hasUsableExit && pFrom->getEast() > 0 && (!pFrom->hasExitLock(DIR_EAST))) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
hasUsableExit = true;
}
if (!hasUsableExit && pFrom->getUp() > 0 && (!pFrom->hasExitLock(DIR_UP))) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
hasUsableExit = true;
}
if (!hasUsableExit && pFrom->getDown() > 0 && (!pFrom->hasExitLock(DIR_DOWN))) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
hasUsableExit = true;
}
if (!hasUsableExit && pFrom->getNortheast() > 0 && (!pFrom->hasExitLock(DIR_NORTHEAST))) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
hasUsableExit = true;
}
if (!hasUsableExit && pFrom->getNorthwest() > 0 && (!pFrom->hasExitLock(DIR_NORTHWEST))) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
hasUsableExit = true;
}
if (!hasUsableExit && pFrom->getSoutheast() > 0 && (!pFrom->hasExitLock(DIR_SOUTHEAST))) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
hasUsableExit = true;
}
if (!hasUsableExit && pFrom->getSouthwest() > 0 && (!pFrom->hasExitLock(DIR_SOUTHWEST))) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
hasUsableExit = true;
}
if (!hasUsableExit && pFrom->getIn() > 0 && (!pFrom->hasExitLock(DIR_IN))) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
hasUsableExit = true;
}
if (!hasUsableExit && pFrom->getOut() > 0 && (!pFrom->hasExitLock(DIR_OUT))) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
hasUsableExit = true;
}
if (!hasUsableExit) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
// No available normal exits from this room so check the special ones
Refactor: store special exits and their lock status separately (#4526) This will enable some simplification of code. During development it became clear that the Lua API `getSpecialExits(...)` function was a bit defective and did not behave as documented in the Wiki: it was only showing one special exit at random that led to a particular exit room in the (admittedly unlikely) event of there being more than one. It also used the special exit name/command as a key in a sub-table with the special exit lock status of that exit as a "0" or "1" string value. This PR repairs the above function by adding an optional boolean argument that: * if omitted or false, replicates the previous behaviour but if there is more than one special exit to the same room it always picks one with the lowest exit weight that is unlocked or if there is none it picks one with the lowest weight that is locked. This will be compatible with old scripts. * if true, returns ALL the exits in the sub-table that lead to the particular room id that is the key in the main table, again those exit commands are the keys with a value being a "0" or "1" depending on whether the exit is unlocked or locked respectively. For the record, the original implementation of special exits was introduced in commit: e0ba28d4729f97f69cd91b178886ad6e7438d9a9 and that was supported by the addition of map format version 6. Locking of Special Exits was added in somewhere between: 19f8563b47454ca6c625c534384b1c7085351dfc and: 070912ea7c84414be2ddb86c371fc791c5718314 (which revised the map format to 11). Also: * use a couple of `const QString`s as templates in the `dlgRoomExit.cpp` file to remove 95 duplicated `QStringLiterals` from the read-only code segment of the compile object file. * add `const` where relevant to some `TRoom` methods. * work harder to ensure than when a special exit is deleted from a `TRoom` then elements that were related to it are also cleaned up. * prepare to save the new `TRoom` data structures in the next Mudlet map file format (21) when it is enabled. In the meantime a workaround to convert the in-game data to the current format is utilised for all current map formats Mudlet can currently use. This will impact a little on the save/loading speeds but that is the cost of simplifying the code that works with special exits elsewhere in the application. * revise and extend the error handling for the room special exit functions generally so that they confirm to our throwing an error on argument type issue (and reporting the faulty argument) and returning `nil` plus an error message for a run-time value problem. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2020-12-31 22:06:00 +00:00
QStringList specialExitCommands = pFrom->getSpecialExits().keys();
while (!specialExitCommands.isEmpty()) {
if (!pFrom->hasSpecialExitLock(specialExitCommands.at(0))) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
hasUsableExit = true;
break;
}
specialExitCommands.removeFirst();
}
}
if (!hasUsableExit) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
qDebug() << "TMap::findPath(" << from << "," << to << ") FAIL: no usable exits from start room!";
return false; // No available exits from the start room so give up!
}
if (!roomidToIndex.contains(from)) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
qDebug() << "TMap::findPath(" << from << "," << to << ") FAIL: start room not in map graph!";
return false;
// The start room is NOT one that has been included in the BGL graph
// probably because it is locked - so no route finding can be done
}
vertex const start = roomidToIndex.value(from);
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
if (!roomidToIndex.contains(to)) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
qDebug() << "TMap::findPath(" << from << "," << to << ") FAIL: target room not in map graph!";
return false;
// The target room is NOT one that has been included in the BGL graph
// probably because it is locked - so no route finding can be done
}
vertex const goal = roomidToIndex.value(to);
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
const auto vertexCount = static_cast<std::size_t>(num_vertices(g));
if (vertexCount == 0) {
qDebug() << "TMap::findPath(" << from << "," << to << ") FAIL: map graph has no vertices.";
return false;
}
if (static_cast<std::size_t>(start) >= vertexCount || static_cast<std::size_t>(goal) >= vertexCount) {
qWarning().nospace().noquote() << "TMap::findPath(" << from << "," << to << ") FAIL: start or target vertex outside of graph range (vertexCount=" << vertexCount << ").";
return false;
}
std::vector<vertex> p(vertexCount);
2017-12-29 16:37:11 +01:00
// Somehow p is an ascending, monotonic series of numbers start at 0, it
// seems we have a redundant indirection in play there as p[0]=0, p[1]=1,..., p[n]=n ...!
std::vector<cost> d(vertexCount);
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
try {
astar_search(g, start, distance_heuristic<mygraph_t, cost, std::vector<location>>(locations, goal), predecessor_map(&p[0]).distance_map(&d[0]).visitor(astar_goal_visitor<vertex>(goal)));
Infrastructure: clear 5 CodeQL warning-level alerts in src/ (#9525) #### Brief overview of PR changes/additions Clears five open CodeQL "warning"-level alerts in `src/`, each with a minimal, behavior-preserving fix: - **`src/TMap.cpp`** (`cpp/catch-by-value`): the A* search catches the `found_goal` sentinel by value. `found_goal` (in `src/TAstar.h`) is an empty struct thrown by the goal visitor purely as a control-flow signal, and the handler never touches the caught object, so it is now caught as `const found_goal&`. - **`src/exitstreewidget.h`** (`cpp/integer-used-for-enum`, two alerts): the special-exit column indices were `static const int` constants, so the two `switch` statements in `dlgRoomExits::slot_editSpecialExit()` dispatched an `int` over const-int case labels. They are now an unscoped `enum ExitsTreeColumn : int` with identical values (0-8). Unscoped keeps the implicit `int` conversions, so every `ExitsTreeWidget::colIndex_*` call site (all passed to Qt column-index `int` parameters) is unchanged. - **`src/TMatchState.h`** (`cpp/rule-of-two`): the class had a user-defined copy constructor but only an implicit copy assignment. Added an explicit `= default` copy assignment. The defaulted assignment reproduces the previous implicit one exactly (full member-wise copy); the existing, deliberately partial copy constructor is untouched. - **`src/TConsole.h`** (`cpp/rule-of-two`): `TFontAttributes` had a `= default` copy assignment but only an implicit copy constructor. Added an explicit `= default` copy constructor. Move operations were already suppressed by the existing user-declared copy assignment, so nothing about copy/move behavior changes. #### Motivation for adding to Mudlet Reduces the open CodeQL alert backlog with small, low-risk hygiene fixes that also make the affected types' intent clearer (explicit special members, a named column enum) without altering any runtime behavior. #### Other info (issues closed, discussion etc) CodeQL alerts cleared: - `cpp/catch-by-value` - `src/TMap.cpp` (alert #140) - `cpp/integer-used-for-enum` - `src/dlgRoomExits.cpp` switch at ~318 (alert #1070) - `cpp/integer-used-for-enum` - `src/dlgRoomExits.cpp` switch at ~399 (alert #1071) - `cpp/rule-of-two` - `src/TMatchState.h` (alert #185) - `cpp/rule-of-two` - `src/TConsole.h` / `TFontAttributes` (alert #2148) Each fix is behavior-preserving. Verified with a full Ninja build (Qt 6.12.0, ASan) and the adjacent functional tests: `MapRoundTripTest`, `TAreaZLevelIndexTest`, `TAreaGridIndexTest`, `TriggerSameLineMatchTest`, `TFeedTriggersRecursionTest`, `ColorTriggerFilterChildTest`, `EnableDisableByNameTest`, `MainConsoleSelectionTest` - all pass.
2026-07-29 10:30:59 +02:00
} catch (const found_goal&) {
qDebug() << "TMap::findPath(" << from << "," << to << ") INFO: time elapsed in A*:" << t.nsecsElapsed() * 1.0e-6 << "ms.";
t.restart();
if (!roomidToIndex.contains(to)) {
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
qDebug() << "TMap::findPath(" << from << "," << to << ") FAIL: target room not in map graph!";
return false;
}
vertex currentVertex = roomidToIndex.value(to);
unsigned int currentRoomId = (locations.at(currentVertex)).id;
// We step through the found path BACKWARDS so advance (well retard)
// the "previous" one first, and it will be the SOURCE vertex for the
// edge and current will be the TARGET vertex:
vertex previousVertex = currentVertex;
do {
previousVertex = p[currentVertex];
if (previousVertex == currentVertex) {
qDebug() << "TMap::findPath(" << from << "," << to << ") WARN: unable to build a path in:" << t.nsecsElapsed() * 1.0e-6 << "ms.";
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
mPathList.clear();
mDirList.clear();
mWeightList.clear(); // Reset any partial results...
return false;
}
Improve: remove speedWalkDir normal exit directions from translation system (#6952) #### Brief overview of PR changes/additions This PR removes the (unhelpful) translation to user's locale. #### Motivation for adding to Mudlet Whilst describing how the SpeedWalking code operated last night on Discord in the **#help** channel: https://www.discord.com/channels/283581582550237184/283582068334526464/1142680496254484561 I realised that we had been passing the normal exit directions through the translation system for the end-users GUI language. This is wrong because there is not necessarily a match between the language the end-user prefers and that used by any MUD they might play. As such it means that the normal exit "abbreviations" that the speedwalking code uses to fill in the `speedWalkDir` table change depending on which GUI language is selected and this means that the "mapper" package for any MUD has to know that and then translate them to the language that the MUD uses - as they need not be the same. #### Other info (issues closed, discussion etc) Examining the various `translations/translated/mudlet_xx_YY.ts` files I have determined that this bogus translation in the user's GUI language happens for the following language/country codes (the code that is used for the others and for all cases when this PR is place without the bogus translation being done AND the "direction codes" also used within the Lua sub-system are also shown): |code|Language (Country)|North|North-east|North-west|East|West|South|South-east|South-west|Up|Down|In|out| |-|-|-|-|-|-|-|-|-|-|-|-|-|-| ||Direction code|`1`|`2`|`3`|`4`|`5`|`6`|`7`|`8`|`9`|`10`|`11`|`12`| ||All others (or after this PR)|`n`|`ne`|`nw`|`e`|`w`|`s`|`se`|`sw`|`up`|`down`|`in`|`out`| |ar_SA|Arabic (Saudi Arabia)|`n`(?)|`ne`(?)|`nw`(?)|`e`(?)|`ص`|`s`(?)|`se`(?)|`sw`(?)|`فوق`|`تحت`|`للداخل`|`للخارج` |de_DE|German (Germany)|`n`|`no`|`nw`|`o`|`w`|`s`|`so`|`sw`|`oben`|`unten`|`rein`|`raus`| |es_ES|Spanish (Spain)|`n`|`ne`|`no`|`e`|`o`|`s`|`se`|`so`|`arriba`|`abajo`|`adentro`|`afuera`| |fr_FR|French (France)|`n`|`ne`|`no`|`e`|`o`|`s`|`se`|`so`|`haut`|`bas`|`entrer`|`sortir`| |it_IT|Italian (Italy)|`n`|`ne`|`no`|`e`|`o`|`s`|`se`|`so`|`alto`|`basso`|`dentro`|`fuori`| |nl_NL|Dutch (Netherlands)|`n`|`no`|`nw`|`o`|`w`|`s`(?)|`zo`|`zw`|`omhoog`|`omlaag`|`in`|`uit`| |pl_PL|Polish (Poland)|`n`|`ne`|`nw`|`e`|`w`|`s`|`se`|`sw`|`u`|`d`|`do środka`|`na zewnątrz`| |pt_BR|Portuguese (Brazil)|`n`|`ne`(?)|`nw`(?)|`e`(?)|`w`(?)|`s`|`se`(?)|`sw`(?)|`cima`|`baixo`|`dentro`|`fora`| |pt_PT|Portuguese (Portugal)|`n`|`ne`(?)|`no`|`e`(?)|`o`|`s`|`se`(?)|`so`|`cima`|`baixo`|`dentro`|`fora`| |ru_RU|Russian (Russia)|`n`|`ne`|`nw`|`e`|`w`|`s`|`se`|`sw`|`up`|`down`|`in`|`out`| |tr_TR|Turkish (Türkiye)|`k`|`kd`|`kb`|`d`|`b`|`g`|`gd`|`gb`|`y`|`a`|`i`|`d`(!)| |zh_TW|Chinese (Traditional)|`n`|`ne`|`nw`|`e`|`w`|`s`|`se`|`sw`|`上`|`下`|`入口`|`出口`| Note that there are some suspect strings in there (?) and also one case where the same code is produced for two different exit directions - which is not just suspect, but probably wrong! --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2023-08-25 17:49:28 +01:00
const unsigned int previousRoomId = (locations.at(previousVertex)).id;
QPair<unsigned int, unsigned int> const edgeRoomIdPair = qMakePair(previousRoomId, currentRoomId);
Improve: remove speedWalkDir normal exit directions from translation system (#6952) #### Brief overview of PR changes/additions This PR removes the (unhelpful) translation to user's locale. #### Motivation for adding to Mudlet Whilst describing how the SpeedWalking code operated last night on Discord in the **#help** channel: https://www.discord.com/channels/283581582550237184/283582068334526464/1142680496254484561 I realised that we had been passing the normal exit directions through the translation system for the end-users GUI language. This is wrong because there is not necessarily a match between the language the end-user prefers and that used by any MUD they might play. As such it means that the normal exit "abbreviations" that the speedwalking code uses to fill in the `speedWalkDir` table change depending on which GUI language is selected and this means that the "mapper" package for any MUD has to know that and then translate them to the language that the MUD uses - as they need not be the same. #### Other info (issues closed, discussion etc) Examining the various `translations/translated/mudlet_xx_YY.ts` files I have determined that this bogus translation in the user's GUI language happens for the following language/country codes (the code that is used for the others and for all cases when this PR is place without the bogus translation being done AND the "direction codes" also used within the Lua sub-system are also shown): |code|Language (Country)|North|North-east|North-west|East|West|South|South-east|South-west|Up|Down|In|out| |-|-|-|-|-|-|-|-|-|-|-|-|-|-| ||Direction code|`1`|`2`|`3`|`4`|`5`|`6`|`7`|`8`|`9`|`10`|`11`|`12`| ||All others (or after this PR)|`n`|`ne`|`nw`|`e`|`w`|`s`|`se`|`sw`|`up`|`down`|`in`|`out`| |ar_SA|Arabic (Saudi Arabia)|`n`(?)|`ne`(?)|`nw`(?)|`e`(?)|`ص`|`s`(?)|`se`(?)|`sw`(?)|`فوق`|`تحت`|`للداخل`|`للخارج` |de_DE|German (Germany)|`n`|`no`|`nw`|`o`|`w`|`s`|`so`|`sw`|`oben`|`unten`|`rein`|`raus`| |es_ES|Spanish (Spain)|`n`|`ne`|`no`|`e`|`o`|`s`|`se`|`so`|`arriba`|`abajo`|`adentro`|`afuera`| |fr_FR|French (France)|`n`|`ne`|`no`|`e`|`o`|`s`|`se`|`so`|`haut`|`bas`|`entrer`|`sortir`| |it_IT|Italian (Italy)|`n`|`ne`|`no`|`e`|`o`|`s`|`se`|`so`|`alto`|`basso`|`dentro`|`fuori`| |nl_NL|Dutch (Netherlands)|`n`|`no`|`nw`|`o`|`w`|`s`(?)|`zo`|`zw`|`omhoog`|`omlaag`|`in`|`uit`| |pl_PL|Polish (Poland)|`n`|`ne`|`nw`|`e`|`w`|`s`|`se`|`sw`|`u`|`d`|`do środka`|`na zewnątrz`| |pt_BR|Portuguese (Brazil)|`n`|`ne`(?)|`nw`(?)|`e`(?)|`w`(?)|`s`|`se`(?)|`sw`(?)|`cima`|`baixo`|`dentro`|`fora`| |pt_PT|Portuguese (Portugal)|`n`|`ne`(?)|`no`|`e`(?)|`o`|`s`|`se`(?)|`so`|`cima`|`baixo`|`dentro`|`fora`| |ru_RU|Russian (Russia)|`n`|`ne`|`nw`|`e`|`w`|`s`|`se`|`sw`|`up`|`down`|`in`|`out`| |tr_TR|Turkish (Türkiye)|`k`|`kd`|`kb`|`d`|`b`|`g`|`gd`|`gb`|`y`|`a`|`i`|`d`(!)| |zh_TW|Chinese (Traditional)|`n`|`ne`|`nw`|`e`|`w`|`s`|`se`|`sw`|`上`|`下`|`入口`|`出口`| Note that there are some suspect strings in there (?) and also one case where the same code is produced for two different exit directions - which is not just suspect, but probably wrong! --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2023-08-25 17:49:28 +01:00
const route r = edgeHash.value(edgeRoomIdPair);
mPathList.prepend(currentRoomId);
Q_ASSERT_X(r.cost > 0, "TMap::findPath()", "broken path {QPair made from source and target roomIds for a path step NOT found in QHash table of all possible steps.}");
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
// Above was found to be triggered by the situation described in:
// https://bugs.launchpad.net/mudlet/+bug/1263447 on 2015-07-17 but
// this is because previousVertex was the same as currentVertex after
// the "previousVertex = p[currentVertex]" operation at the start of
// the do{} loop - added a test for this so should bail out if it
// happens - Slysven
mWeightList.prepend(r.cost);
Improve: remove speedWalkDir normal exit directions from translation system (#6952) #### Brief overview of PR changes/additions This PR removes the (unhelpful) translation to user's locale. #### Motivation for adding to Mudlet Whilst describing how the SpeedWalking code operated last night on Discord in the **#help** channel: https://www.discord.com/channels/283581582550237184/283582068334526464/1142680496254484561 I realised that we had been passing the normal exit directions through the translation system for the end-users GUI language. This is wrong because there is not necessarily a match between the language the end-user prefers and that used by any MUD they might play. As such it means that the normal exit "abbreviations" that the speedwalking code uses to fill in the `speedWalkDir` table change depending on which GUI language is selected and this means that the "mapper" package for any MUD has to know that and then translate them to the language that the MUD uses - as they need not be the same. #### Other info (issues closed, discussion etc) Examining the various `translations/translated/mudlet_xx_YY.ts` files I have determined that this bogus translation in the user's GUI language happens for the following language/country codes (the code that is used for the others and for all cases when this PR is place without the bogus translation being done AND the "direction codes" also used within the Lua sub-system are also shown): |code|Language (Country)|North|North-east|North-west|East|West|South|South-east|South-west|Up|Down|In|out| |-|-|-|-|-|-|-|-|-|-|-|-|-|-| ||Direction code|`1`|`2`|`3`|`4`|`5`|`6`|`7`|`8`|`9`|`10`|`11`|`12`| ||All others (or after this PR)|`n`|`ne`|`nw`|`e`|`w`|`s`|`se`|`sw`|`up`|`down`|`in`|`out`| |ar_SA|Arabic (Saudi Arabia)|`n`(?)|`ne`(?)|`nw`(?)|`e`(?)|`ص`|`s`(?)|`se`(?)|`sw`(?)|`فوق`|`تحت`|`للداخل`|`للخارج` |de_DE|German (Germany)|`n`|`no`|`nw`|`o`|`w`|`s`|`so`|`sw`|`oben`|`unten`|`rein`|`raus`| |es_ES|Spanish (Spain)|`n`|`ne`|`no`|`e`|`o`|`s`|`se`|`so`|`arriba`|`abajo`|`adentro`|`afuera`| |fr_FR|French (France)|`n`|`ne`|`no`|`e`|`o`|`s`|`se`|`so`|`haut`|`bas`|`entrer`|`sortir`| |it_IT|Italian (Italy)|`n`|`ne`|`no`|`e`|`o`|`s`|`se`|`so`|`alto`|`basso`|`dentro`|`fuori`| |nl_NL|Dutch (Netherlands)|`n`|`no`|`nw`|`o`|`w`|`s`(?)|`zo`|`zw`|`omhoog`|`omlaag`|`in`|`uit`| |pl_PL|Polish (Poland)|`n`|`ne`|`nw`|`e`|`w`|`s`|`se`|`sw`|`u`|`d`|`do środka`|`na zewnątrz`| |pt_BR|Portuguese (Brazil)|`n`|`ne`(?)|`nw`(?)|`e`(?)|`w`(?)|`s`|`se`(?)|`sw`(?)|`cima`|`baixo`|`dentro`|`fora`| |pt_PT|Portuguese (Portugal)|`n`|`ne`(?)|`no`|`e`(?)|`o`|`s`|`se`(?)|`so`|`cima`|`baixo`|`dentro`|`fora`| |ru_RU|Russian (Russia)|`n`|`ne`|`nw`|`e`|`w`|`s`|`se`|`sw`|`up`|`down`|`in`|`out`| |tr_TR|Turkish (Türkiye)|`k`|`kd`|`kb`|`d`|`b`|`g`|`gd`|`gb`|`y`|`a`|`i`|`d`(!)| |zh_TW|Chinese (Traditional)|`n`|`ne`|`nw`|`e`|`w`|`s`|`se`|`sw`|`上`|`下`|`入口`|`出口`| Note that there are some suspect strings in there (?) and also one case where the same code is produced for two different exit directions - which is not just suspect, but probably wrong! --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2023-08-25 17:49:28 +01:00
switch (r.direction) {
/*
* Do not translate the directions into the user's locale here,
* that is to be done in the profile specific doSpeedwalk()
* function of the mapper package as the language of the MUD
* need not be the native language of the user - translating
* them here makes the mapper harder to code as it has to
* accommodate all the possible languages the GUI of Mudlet was
* configured to support!
*/
case DIR_NORTH:
mDirList.prepend(qsl("n"));
break;
case DIR_NORTHEAST:
mDirList.prepend(qsl("ne"));
break;
case DIR_EAST:
mDirList.prepend(qsl("e"));
break;
case DIR_SOUTHEAST:
mDirList.prepend(qsl("se"));
break;
case DIR_SOUTH:
mDirList.prepend(qsl("s"));
break;
case DIR_SOUTHWEST:
mDirList.prepend(qsl("sw"));
break;
case DIR_WEST:
mDirList.prepend(qsl("w"));
break;
case DIR_NORTHWEST:
mDirList.prepend(qsl("nw"));
break;
case DIR_UP:
mDirList.prepend(qsl("up"));
break;
case DIR_DOWN:
mDirList.prepend(qsl("down"));
break;
case DIR_IN:
mDirList.prepend(qsl("in"));
break;
case DIR_OUT:
mDirList.prepend(qsl("out"));
break;
case DIR_OTHER:
mDirList.prepend(r.specialExitName);
break;
default:
qWarning().nospace().noquote() << "TMap::findPath(" << from << ", " << to << ") WARNING - found route between rooms (from id: " << previousRoomId << ", to id: " << currentRoomId
<< ") with an invalid DIR_xxxx code: " << r.direction << " - the path will not be valid!";
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
}
currentVertex = previousVertex;
currentRoomId = previousRoomId;
} while (currentVertex != start);
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
qDebug() << "TMap::findPath(" << from << "," << to << ") INFO: found path in:" << t.nsecsElapsed() * 1.0e-6 << "ms.";
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
return true;
}
qDebug() << "TMap::findPath(" << from << "," << to << ") INFO: did NOT find path in:" << t.nsecsElapsed() * 1.0e-6 << "ms.";
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
return false;
2010-08-25 00:41:43 +02:00
}
bool TMap::serialize(QDataStream& ofs, int saveVersion)
2010-08-25 00:41:43 +02:00
{
fix: seven Lua library and mapper bugs found while speccing them (#9815) Stacked on #9799, so the base is `fix-db-index-string` and this retargets to development once that merges. - `table.contains()` keeps a set of the tables it has walked, so a self-referential one (every Geyser object holds its container, which holds it back) answers instead of overflowing the stack, and `Geyser.Label:setDoubleClickCallback()` stores the `doubleClickCallback` key the label's own re-registration reads rather than one nothing reads. - db: a `UNIQUE` with no `ON CONFLICT` clause is now seen, so a change in uniqueness rebuilds the sheet; a sheet given as a list of column names takes the sheet options instead of swallowing `_index` as a phantom column; and an `_index` naming a column the sheet does not have is refused rather than quietly dropping the indexes the sheet already had. - `saveMap()` resolves a relative location against the profile directory the way `importMap()` does instead of against the directory Mudlet was started in, `loadMap()` looks in the same place, and a format version below the oldest one Mudlet can write is refused the way one that is too new already was. Test case: `lua local t = {} t.self = t display(table.contains(t, "x"))` answers `false` instead of raising, and `lua saveMap(42)` writes into `getMudletHomeDir()` rather than the directory Mudlet was started in. Worth knowing: `db:create` now hard-errors on an `_index` naming a column the sheet does not declare, where it used to load and silently lose the sheet's indexes. Closes #9777, Closes #9779, Closes #9780, Closes #9781, Closes #9782, Closes #9800, Closes #9801 Assisted-by: Claude:claude-opus-5
2026-08-12 11:28:07 +02:00
if (saveVersion > mMaxVersion) {
const QString errMsg = tr("[ ERROR ] - The format version \"%1\" you are trying to save the map with is too new\n"
"for this version of Mudlet. Supported are only formats up to version %2.")
.arg(QString::number(saveVersion), QString::number(mMaxVersion));
appendErrorMsgWithNoLf(errMsg, false);
postMessage(errMsg);
return false;
}
fix: seven Lua library and mapper bugs found while speccing them (#9815) Stacked on #9799, so the base is `fix-db-index-string` and this retargets to development once that merges. - `table.contains()` keeps a set of the tables it has walked, so a self-referential one (every Geyser object holds its container, which holds it back) answers instead of overflowing the stack, and `Geyser.Label:setDoubleClickCallback()` stores the `doubleClickCallback` key the label's own re-registration reads rather than one nothing reads. - db: a `UNIQUE` with no `ON CONFLICT` clause is now seen, so a change in uniqueness rebuilds the sheet; a sheet given as a list of column names takes the sheet options instead of swallowing `_index` as a phantom column; and an `_index` naming a column the sheet does not have is refused rather than quietly dropping the indexes the sheet already had. - `saveMap()` resolves a relative location against the profile directory the way `importMap()` does instead of against the directory Mudlet was started in, `loadMap()` looks in the same place, and a format version below the oldest one Mudlet can write is refused the way one that is too new already was. Test case: `lua local t = {} t.self = t display(table.contains(t, "x"))` answers `false` instead of raising, and `lua saveMap(42)` writes into `getMudletHomeDir()` rather than the directory Mudlet was started in. Worth knowing: `db:create` now hard-errors on an `_index` naming a column the sheet does not declare, where it used to load and silently lose the sheet's indexes. Closes #9777, Closes #9779, Closes #9780, Closes #9781, Closes #9782, Closes #9800, Closes #9801 Assisted-by: Claude:claude-opus-5
2026-08-12 11:28:07 +02:00
if (saveVersion != 0 && saveVersion < mMinVersion) {
//: Shown when a map save asks for a format version older than this Mudlet can write. %1 is the version asked for, %2 the oldest one supported.
const QString errMsg = tr("[ ERROR ] - The format version \"%1\" you are trying to save the map with is too old\n"
"for this version of Mudlet. Supported are only formats from version %2.")
.arg(QString::number(saveVersion), QString::number(mMinVersion));
appendErrorMsgWithNoLf(errMsg, false);
postMessage(errMsg);
return false;
}
auto oldSaveVersion = mSaveVersion;
// if 0 we default to current version selected
if (saveVersion != 0) {
mSaveVersion = saveVersion;
}
if (mSaveVersion != mVersion) {
const QString message = tr("[ ALERT ] - Saving map in format version \"%1\" that is different than \"%2\" which\n"
"it was loaded as. This may be an issue if you want to share the resulting\n"
"map with others relying on the original format.")
.arg(mSaveVersion)
.arg(mVersion);
appendErrorMsgWithNoLf(message, false);
mpHost->mTelnet.postMessage(message);
}
if (mSaveVersion != mDefaultVersion) {
const QString message = tr("[ WARN ] - Saving map in format version \"%1\" different from the\n"
"recommended map version %2 for this version of Mudlet.")
.arg(mSaveVersion)
.arg(mDefaultVersion);
appendErrorMsgWithNoLf(message, false);
postMessage(message);
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
}
ofs << mSaveVersion;
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
ofs << mEnvColors;
2013-03-22 12:47:58 +01:00
ofs << mpRoomDB->getAreaNamesMap();
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
ofs << mCustomEnvColors;
ofs << mpRoomDB->hashToRoomID;
Update: drop support for saving to Mudlet 2.1 map format & update default This PR removes support for saving in the binary map file format of Mudlet 2.1 - i.e. format **16** (retaining the ability to read it) and adjusts the format for new map files to be **20** by default - up from the previous default of **18**. This should speed up map loading a little - as it will remove the need to convert the data to the current forms used internally as well as making some details more robust. It also allows the removal of some warning code that would have fired if area or map user data features were used and format *16* was selected for saving. #### History of recent (last six years) changes to Map File Format: * dfce0f01ade0a5e330a699fbe2c747c5eb6b3a5d (PR #2106) - **20** Improved way that custom exit line data was held internally (so that the keys are now the same as the other exit details that are keyed by a string {doors, exit weight}. The custom exit line style is stored as the shorter and easier to code with `Qt::PenStyle enum` instead of a English `QString` and the custom exit line as a `QColor` instead of a `QList<int>` with 3 elements - (so the custom exit line could have a alpha component in the future!) Code is in place to support a workaround to work within map formats back to include version 17. * 91a08c33f29b7147b38b6649e03cc8cc6639fce4 (PR #1543) - **19** Added support for more than one of any grapheme for the 2D map room symbol. Code is in place to support a workaround to work within map formats back to include version 17. * 94dd41bfb7ab203565c9397717d04eb22dc9810c (associated with PR #301) - **18** Added support for multiple user rooms in map file copied to other profiles - so that the original player room (in the other profile) is retained in a map copied over. Also revised the `TArea::rooms` from being a `QList` to a faster to look up in `QSet`. Code in place to support saving in previous formats. * fb79c62381fde12e5d4dae711b382e3f3d914c8f (associated with PR #280) - **17** Added support for area and map user data features. Warnings are issued should these be actually used and a lower map format is specified to save the map in **as that data will then be lost from the map file**. * 88ef6491e04bc73c61d4c5577c67d9c73b235a8a - **16** Map format of Mudlet 2.1 dating back to 2013-01-02 . Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2019-08-16 22:07:07 +02:00
if (mSaveVersion < 19) {
// Save the data in the map user data for older versions - use a local
// copy so that saving does not modify the live map's user data:
QMap<QString, QString> userData{mUserData};
userData.insert(qsl("system.fallback_mapSymbolFont"), mMapSymbolFont.toString());
userData.insert(qsl("system.fallback_mapSymbolFontFudgeFactor"), QString::number(mMapSymbolFontFudgeFactor));
userData.insert(qsl("system.fallback_onlyUseMapSymbolFont"), mIsOnlyMapSymbolFontToBeUsed ? qsl("true") : qsl("false"));
ofs << userData;
} else {
ofs << mUserData;
Update: drop support for saving to Mudlet 2.1 map format & update default This PR removes support for saving in the binary map file format of Mudlet 2.1 - i.e. format **16** (retaining the ability to read it) and adjusts the format for new map files to be **20** by default - up from the previous default of **18**. This should speed up map loading a little - as it will remove the need to convert the data to the current forms used internally as well as making some details more robust. It also allows the removal of some warning code that would have fired if area or map user data features were used and format *16* was selected for saving. #### History of recent (last six years) changes to Map File Format: * dfce0f01ade0a5e330a699fbe2c747c5eb6b3a5d (PR #2106) - **20** Improved way that custom exit line data was held internally (so that the keys are now the same as the other exit details that are keyed by a string {doors, exit weight}. The custom exit line style is stored as the shorter and easier to code with `Qt::PenStyle enum` instead of a English `QString` and the custom exit line as a `QColor` instead of a `QList<int>` with 3 elements - (so the custom exit line could have a alpha component in the future!) Code is in place to support a workaround to work within map formats back to include version 17. * 91a08c33f29b7147b38b6649e03cc8cc6639fce4 (PR #1543) - **19** Added support for more than one of any grapheme for the 2D map room symbol. Code is in place to support a workaround to work within map formats back to include version 17. * 94dd41bfb7ab203565c9397717d04eb22dc9810c (associated with PR #301) - **18** Added support for multiple user rooms in map file copied to other profiles - so that the original player room (in the other profile) is retained in a map copied over. Also revised the `TArea::rooms` from being a `QList` to a faster to look up in `QSet`. Code in place to support saving in previous formats. * fb79c62381fde12e5d4dae711b382e3f3d914c8f (associated with PR #280) - **17** Added support for area and map user data features. Warnings are issued should these be actually used and a lower map format is specified to save the map in **as that data will then be lost from the map file**. * 88ef6491e04bc73c61d4c5577c67d9c73b235a8a - **16** Map format of Mudlet 2.1 dating back to 2013-01-02 . Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2019-08-16 22:07:07 +02:00
// Save the data directly in supported format versions (19 and above)
ofs << mMapSymbolFont;
ofs << mMapSymbolFontFudgeFactor;
ofs << mIsOnlyMapSymbolFontToBeUsed;
Fixup: correct some issues raised in testing * In dlgTrigger C'tor tweaked Qt Version check for inclusion of placeholder text - should be 5.3 not 5.2. * In source_editor_area.ui restore the full-widget background painting - which otherwise limited the background colour to the extent of the content not the widget and when reviewed was NOT wanted. * In dlgTriggerEditor::slot_cursorPositionChanged() rearrange "current position" details to a more acceptable order with line counts first. * Initialise Host::mTimerDebugOutputSuppressionInterval member so that the adjustment control in "Profile Preferences" comes up with a consistent value on first use. When testing it became clear that the behaviour when moving away from the zero "Show all" value would start acting on the most significant section ("Hours") rather than the more useful "Seconds". Added void dlgProfilePreferences::slot_timeValueChanged(QTime) private slot connect to the timeChanged(QTime) signal to handle things. Whilst fixing the above things I also became aware of and addressed: * When the Profile Preferences dialog is open the map format save control was not being initialised to the current setting but to the default 16 instead - this is confusing for someone who HAS changed the value and goes back to see it reset - even though it has not been until they close (and thus save) whatever the value. * Absence of tool-tips for Profile Preference Special Option mentioned above to cut down spam from short interval Timers and also the map save version override control. * There are already warning in place the first time that the Lua set{Map|Area}UserData(...) commands are used and the map format is not 17 but this is is now detected on map save. However as this can happen when the user closes Mudlet and they won't get displayed in time the other warnings are still useful - both of these can be removed in the future when the current format of 16 is not longer available. * Spotted a potential bug in that when saving rooms there is not a null room pointer check to skip the (hopefully) unlikely case of a QHash<int, TRoom*>TRoomDB:rooms value being null - this would cause a null pointer bug and thus a probable crash when straigt afterward that pointer would be dereferenced. * The Editor toolbar button to show/hide the search area also shows and hides the area where "Errors" {"popupArea"} are displayed within the Editor widget. Probably a long standing issue from the past evolution of the editor. * Spotted that the statusBar tip for the "copy HTML" context menu command for the TTextEdit class was being applied to the "copy" entry - so that the "copy" command got the wrong text and the "copy HTML" did not have any statusBer Tip. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-05 06:48:08 +00:00
}
// Qt 6 changed the return type of QMap<T1, T2>::size() to qsizetype which
// is an int64 rather than the int32 of Qt5 - but we need to use the latter
// to retain compatibility:
ofs << static_cast<qint32>(mpRoomDB->getAreaMap().size());
// serialize area table
QMapIterator<int, TArea*> itAreaList(mpRoomDB->getAreaMap());
while (itAreaList.hasNext()) {
itAreaList.next();
const int areaID = itAreaList.key();
TArea* pA = itAreaList.value();
ofs << areaID;
if (mSaveVersion >= 18) {
ofs << pA->rooms;
} else {
// Switched to a (faster) QSet<int> from a QList<int> in version 18
QList<int> const _oldList = pA->rooms.values();
ofs << _oldList;
}
ofs << pA->zLevels;
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
ofs << pA->mAreaExits;
ofs << pA->gridMode;
ofs << pA->max_x;
ofs << pA->max_y;
ofs << pA->max_z;
ofs << pA->min_x;
ofs << pA->min_y;
ofs << pA->min_z;
ofs << pA->span;
Update: drop support for saving to Mudlet 2.1 map format & update default This PR removes support for saving in the binary map file format of Mudlet 2.1 - i.e. format **16** (retaining the ability to read it) and adjusts the format for new map files to be **20** by default - up from the previous default of **18**. This should speed up map loading a little - as it will remove the need to convert the data to the current forms used internally as well as making some details more robust. It also allows the removal of some warning code that would have fired if area or map user data features were used and format *16* was selected for saving. #### History of recent (last six years) changes to Map File Format: * dfce0f01ade0a5e330a699fbe2c747c5eb6b3a5d (PR #2106) - **20** Improved way that custom exit line data was held internally (so that the keys are now the same as the other exit details that are keyed by a string {doors, exit weight}. The custom exit line style is stored as the shorter and easier to code with `Qt::PenStyle enum` instead of a English `QString` and the custom exit line as a `QColor` instead of a `QList<int>` with 3 elements - (so the custom exit line could have a alpha component in the future!) Code is in place to support a workaround to work within map formats back to include version 17. * 91a08c33f29b7147b38b6649e03cc8cc6639fce4 (PR #1543) - **19** Added support for more than one of any grapheme for the 2D map room symbol. Code is in place to support a workaround to work within map formats back to include version 17. * 94dd41bfb7ab203565c9397717d04eb22dc9810c (associated with PR #301) - **18** Added support for multiple user rooms in map file copied to other profiles - so that the original player room (in the other profile) is retained in a map copied over. Also revised the `TArea::rooms` from being a `QList` to a faster to look up in `QSet`. Code in place to support saving in previous formats. * fb79c62381fde12e5d4dae711b382e3f3d914c8f (associated with PR #280) - **17** Added support for area and map user data features. Warnings are issued should these be actually used and a lower map format is specified to save the map in **as that data will then be lost from the map file**. * 88ef6491e04bc73c61d4c5577c67d9c73b235a8a - **16** Map format of Mudlet 2.1 dating back to 2013-01-02 . Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2019-08-16 22:07:07 +02:00
ofs << pA->xmaxForZ;
ofs << pA->ymaxForZ;
ofs << pA->xminForZ;
ofs << pA->yminForZ;
ofs << pA->pos;
ofs << pA->isZone;
ofs << pA->zoneAreaRef;
Improve: remember 2D mapper zoom amounts between sessions (#6615) This is intended to close #2388. This enables the 2D (only) map zoom amounts for each map area to be save independently and restored when switching between areas in the mapper. It also saves the data between session. It extends the existing `setMapZoom(...)` API to take an optional second argument to specify the map area ID to set the zoom (which is a floating point number) for any existing area, not just the current one. It also adds a `getMapZoom(...)` function that, without any arguments, returns the currently used 2D map zoom value for the area currently being shown in the 2D mapper. If an area ID is provided it instead returns the value that was last used for that area - or the default value that is used initially on starting the profile or for an area that has not been viewed before. Importantly when switching between the areas in the 2D mapper the values are retained and applied so that one area can be zoomed in and another zoomed out and switching from the first to the second and back to the first means that the zoom level used in the first is reused when it is returned to. Deleting an area will forget the stored zoom level so if it is reused it starts from scratch. Code to save the zoom level for each area has also been implemented within the C++ core. It saves it in the Area User Data for current map formats (but removes it on loading so the user never sees it there) under a `system.fallback_map2DZoom` key but will save it directly in the binary data (which is more efficient) in the next format version whenever it is enabled. A new Mudlet event, which has been called `sysMapAreaChanged` has been added with two additional arguments being the area ID changed to followed by the one that it was changed from. I originally thought I would need it to handle saving the zoom level for each area via the Lua system but I found that that was not practicable. Also, in refactoring `T2DMap::paintEvent(...)` I: Removed/combined some locals: * `(TArea*) playerArea` and `pPlayerArea` and `pArea`==> `pDrawnArea` * `(TRoom*) playerRoom` ==> `pPlayerRoom` Remove unneeded (refactored out): * `(qreal) ox` * `(qreal) oy` Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2023-03-16 15:00:33 +00:00
if (mSaveVersion >= 21) {
// Revised in version 21 to store the value directly:
ofs << pA->mLast2DMapZoom;
} else {
pA->mUserData.insert(QLatin1String("system.fallback_map2DZoom"), QString::number(pA->get2DMapZoom()));
}
// Store font and outline color info for labels in userData (avoids binary format version change)
const auto permanentLabelsList{pA->getPermanentLabelIds()};
for (const auto labelID : permanentLabelsList) {
const auto label = pA->mMapLabels.value(labelID);
if (!label.font.family().isEmpty()) {
if (label.font.family().contains(QLatin1Char('|'))) {
qWarning("TMap::serialize() - Font family '%s' for label %d contains pipe character, font may not deserialize correctly", qUtf8Printable(label.font.family()), labelID);
}
const QString fontKey = qsl("system.labelFont_%1").arg(labelID);
const QString fontValue = qsl("%1|%2|%3|%4").arg(label.font.family()).arg(label.font.pointSize()).arg(label.font.weight()).arg(label.font.italic() ? 1 : 0);
pA->mUserData.insert(fontKey, fontValue);
}
const QString outlineColorKey = qsl("system.labelOutlineColor_%1").arg(labelID);
const QString outlineColorValue = qsl("%1|%2|%3|%4").arg(label.outlineColor.red()).arg(label.outlineColor.green()).arg(label.outlineColor.blue()).arg(label.outlineColor.alpha());
pA->mUserData.insert(outlineColorKey, outlineColorValue);
}
Update: drop support for saving to Mudlet 2.1 map format & update default This PR removes support for saving in the binary map file format of Mudlet 2.1 - i.e. format **16** (retaining the ability to read it) and adjusts the format for new map files to be **20** by default - up from the previous default of **18**. This should speed up map loading a little - as it will remove the need to convert the data to the current forms used internally as well as making some details more robust. It also allows the removal of some warning code that would have fired if area or map user data features were used and format *16* was selected for saving. #### History of recent (last six years) changes to Map File Format: * dfce0f01ade0a5e330a699fbe2c747c5eb6b3a5d (PR #2106) - **20** Improved way that custom exit line data was held internally (so that the keys are now the same as the other exit details that are keyed by a string {doors, exit weight}. The custom exit line style is stored as the shorter and easier to code with `Qt::PenStyle enum` instead of a English `QString` and the custom exit line as a `QColor` instead of a `QList<int>` with 3 elements - (so the custom exit line could have a alpha component in the future!) Code is in place to support a workaround to work within map formats back to include version 17. * 91a08c33f29b7147b38b6649e03cc8cc6639fce4 (PR #1543) - **19** Added support for more than one of any grapheme for the 2D map room symbol. Code is in place to support a workaround to work within map formats back to include version 17. * 94dd41bfb7ab203565c9397717d04eb22dc9810c (associated with PR #301) - **18** Added support for multiple user rooms in map file copied to other profiles - so that the original player room (in the other profile) is retained in a map copied over. Also revised the `TArea::rooms` from being a `QList` to a faster to look up in `QSet`. Code in place to support saving in previous formats. * fb79c62381fde12e5d4dae711b382e3f3d914c8f (associated with PR #280) - **17** Added support for area and map user data features. Warnings are issued should these be actually used and a lower map format is specified to save the map in **as that data will then be lost from the map file**. * 88ef6491e04bc73c61d4c5577c67d9c73b235a8a - **16** Map format of Mudlet 2.1 dating back to 2013-01-02 . Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2019-08-16 22:07:07 +02:00
ofs << pA->mUserData;
if (mSaveVersion >= 21) {
// Revised in version 21 to store labels within the TArea class:
// Also we now have temporary labels, so we need to count the
// permanent ones first to use as the count for ones to store:
ofs << static_cast<qint32>(permanentLabelsList.size());
QListIterator<int> itMapLabelId(permanentLabelsList);
while (itMapLabelId.hasNext()) {
const auto labelID = itMapLabelId.next();
const auto label = pA->mMapLabels.value(labelID);
ofs << labelID;
ofs << label.pos;
ofs << label.size;
ofs << label.text;
ofs << label.fgColor;
ofs << label.bgColor;
ofs << label.pix;
ofs << label.noScaling;
ofs << label.showOnTop;
}
}
Fixup: correct some issues raised in testing * In dlgTrigger C'tor tweaked Qt Version check for inclusion of placeholder text - should be 5.3 not 5.2. * In source_editor_area.ui restore the full-widget background painting - which otherwise limited the background colour to the extent of the content not the widget and when reviewed was NOT wanted. * In dlgTriggerEditor::slot_cursorPositionChanged() rearrange "current position" details to a more acceptable order with line counts first. * Initialise Host::mTimerDebugOutputSuppressionInterval member so that the adjustment control in "Profile Preferences" comes up with a consistent value on first use. When testing it became clear that the behaviour when moving away from the zero "Show all" value would start acting on the most significant section ("Hours") rather than the more useful "Seconds". Added void dlgProfilePreferences::slot_timeValueChanged(QTime) private slot connect to the timeChanged(QTime) signal to handle things. Whilst fixing the above things I also became aware of and addressed: * When the Profile Preferences dialog is open the map format save control was not being initialised to the current setting but to the default 16 instead - this is confusing for someone who HAS changed the value and goes back to see it reset - even though it has not been until they close (and thus save) whatever the value. * Absence of tool-tips for Profile Preference Special Option mentioned above to cut down spam from short interval Timers and also the map save version override control. * There are already warning in place the first time that the Lua set{Map|Area}UserData(...) commands are used and the map format is not 17 but this is is now detected on map save. However as this can happen when the user closes Mudlet and they won't get displayed in time the other warnings are still useful - both of these can be removed in the future when the current format of 16 is not longer available. * Spotted a potential bug in that when saving rooms there is not a null room pointer check to skip the (hopefully) unlikely case of a QHash<int, TRoom*>TRoomDB:rooms value being null - this would cause a null pointer bug and thus a probable crash when straigt afterward that pointer would be dereferenced. * The Editor toolbar button to show/hide the search area also shows and hides the area where "Errors" {"popupArea"} are displayed within the Editor widget. Probably a long standing issue from the past evolution of the editor. * Spotted that the statusBar tip for the "copy HTML" context menu command for the TTextEdit class was being applied to the "copy" entry - so that the "copy" command got the wrong text and the "copy HTML" did not have any statusBer Tip. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-05 06:48:08 +00:00
}
if (mSaveVersion >= 18) {
// Revised in version 18 to store mRoomId as a per profile case so that
// sharing/copying between profiles respects each profile's player
// location
ofs << mRoomIdHash;
} else {
ofs << mRoomIdHash.value(mProfileName);
}
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
if (mSaveVersion < 21) {
// Before version 21 the map labels were stored within this class:
// First we have the number of labels per area - we need this as there
// is no delimiter between each area's map labels
QMap<int, TArea*> areasWithPermanentLabels;
// Need to count the areas that have mapLabels:
QMapIterator<int, TArea*> itArea(mpRoomDB->getAreaMap());
while (itArea.hasNext()) {
// Now we have temporary labels we need to identify areas with
// permanent ones:
itArea.next();
auto pArea = itArea.value();
if (pArea && !pArea->mMapLabels.isEmpty() && pArea->hasPermanentLabels()) {
areasWithPermanentLabels.insert(itArea.key(), itArea.value());
}
}
ofs << static_cast<qint32>(areasWithPermanentLabels.count());
QMapIterator<int, TArea*> itAreaWithLabels(areasWithPermanentLabels);
while (itAreaWithLabels.hasNext()) {
itAreaWithLabels.next();
auto pArea = itAreaWithLabels.value();
auto permanentLabelIdsList = pArea->getPermanentLabelIds();
// number of (permanent) labels in this area:
ofs << static_cast<qint32>(permanentLabelIdsList.size());
// only used to assign labels to the area:
ofs << itAreaWithLabels.key();
QListIterator<int> itPerminentMapLabelIds(permanentLabelIdsList);
while (itPerminentMapLabelIds.hasNext()) {
auto labelID = itPerminentMapLabelIds.next();
ofs << labelID; //label ID
TMapLabel const label = pArea->mMapLabels.value(labelID);
ofs << label.pos;
ofs << QPointF(); // dummy value - not actually used
ofs << label.size;
ofs << label.text;
ofs << label.fgColor;
ofs << label.bgColor;
ofs << label.pix;
ofs << label.noScaling;
ofs << label.showOnTop;
}
2011-06-26 23:26:24 +02:00
}
}
QHashIterator<int, TRoom*> it(mpRoomDB->getRoomMap());
while (it.hasNext()) {
2010-08-25 00:41:43 +02:00
it.next();
TRoom* pR = it.value();
if (!pR) {
qDebug() << "TMap::serialize(...) skipping a room with a NULL TRoom pointer:" << it.key();
Fixup: correct some issues raised in testing * In dlgTrigger C'tor tweaked Qt Version check for inclusion of placeholder text - should be 5.3 not 5.2. * In source_editor_area.ui restore the full-widget background painting - which otherwise limited the background colour to the extent of the content not the widget and when reviewed was NOT wanted. * In dlgTriggerEditor::slot_cursorPositionChanged() rearrange "current position" details to a more acceptable order with line counts first. * Initialise Host::mTimerDebugOutputSuppressionInterval member so that the adjustment control in "Profile Preferences" comes up with a consistent value on first use. When testing it became clear that the behaviour when moving away from the zero "Show all" value would start acting on the most significant section ("Hours") rather than the more useful "Seconds". Added void dlgProfilePreferences::slot_timeValueChanged(QTime) private slot connect to the timeChanged(QTime) signal to handle things. Whilst fixing the above things I also became aware of and addressed: * When the Profile Preferences dialog is open the map format save control was not being initialised to the current setting but to the default 16 instead - this is confusing for someone who HAS changed the value and goes back to see it reset - even though it has not been until they close (and thus save) whatever the value. * Absence of tool-tips for Profile Preference Special Option mentioned above to cut down spam from short interval Timers and also the map save version override control. * There are already warning in place the first time that the Lua set{Map|Area}UserData(...) commands are used and the map format is not 17 but this is is now detected on map save. However as this can happen when the user closes Mudlet and they won't get displayed in time the other warnings are still useful - both of these can be removed in the future when the current format of 16 is not longer available. * Spotted a potential bug in that when saving rooms there is not a null room pointer check to skip the (hopefully) unlikely case of a QHash<int, TRoom*>TRoomDB:rooms value being null - this would cause a null pointer bug and thus a probable crash when straigt afterward that pointer would be dereferenced. * The Editor toolbar button to show/hide the search area also shows and hides the area where "Errors" {"popupArea"} are displayed within the Editor widget. Probably a long standing issue from the past evolution of the editor. * Spotted that the statusBar tip for the "copy HTML" context menu command for the TTextEdit class was being applied to the "copy" entry - so that the "copy" command got the wrong text and the "copy HTML" did not have any statusBer Tip. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-05 06:48:08 +00:00
continue;
}
ofs << pR->getId();
2013-03-22 12:47:58 +01:00
ofs << pR->getArea();
Infrastructure: make TRoom coordinates private (#7539) #### Summary of PR Changes/Additions Makes the coordinate members of the `TRoom` class private so that access to them can be tracked via methods to set and get them. #### Motivation for Adding to Mudlet This is so that the setters can then subsequently include any extra code that needs to be aware when the room is moved. I intend to improve the detection of rooms being placed in the same position but realised this would be a good preliminary step. #### Additional Information (related issues, discussions, etc.) Removes some dead code setting but not using `(int) quads` and `(int) verts` in `(void) GLWidget::paintGL()` Also using the mouse to drag and thus move selected rooms when those rooms were on different levels would squash them all down to be on the same z-coordinate as the "highlighted centre of the selection" room. This is not as helpful it might seem and instead increased the likelihood of causing room collisions - so now each room will retain it's z coordinate if it is not on the same level as the centre of the multiple room selection. Also move code that likely needs to be run whenever rooms are added/removed/moved within an area to a common block of code (`(void) TArea::clean()`) to help keep things DRY. I intend to put code to update a per area record of rooms that are in the same place within that block in the future - so that the record can be reused without having to be repeatedly recalculated, especially in the paint event for the 2D mapper. --------- Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2024-12-09 14:29:13 +00:00
ofs << pR->x();
ofs << pR->y();
ofs << pR->z();
2013-03-22 12:47:58 +01:00
ofs << pR->getNorth();
ofs << pR->getNortheast();
ofs << pR->getEast();
ofs << pR->getSoutheast();
ofs << pR->getSouth();
ofs << pR->getSouthwest();
ofs << pR->getWest();
ofs << pR->getNorthwest();
ofs << pR->getUp();
ofs << pR->getDown();
ofs << pR->getIn();
ofs << pR->getOut();
ofs << pR->environment;
2013-05-26 11:47:15 +02:00
ofs << pR->getWeight();
2013-03-22 12:47:58 +01:00
ofs << pR->name;
ofs << pR->isLocked;
Refactor: store special exits and their lock status separately (#4526) This will enable some simplification of code. During development it became clear that the Lua API `getSpecialExits(...)` function was a bit defective and did not behave as documented in the Wiki: it was only showing one special exit at random that led to a particular exit room in the (admittedly unlikely) event of there being more than one. It also used the special exit name/command as a key in a sub-table with the special exit lock status of that exit as a "0" or "1" string value. This PR repairs the above function by adding an optional boolean argument that: * if omitted or false, replicates the previous behaviour but if there is more than one special exit to the same room it always picks one with the lowest exit weight that is unlocked or if there is none it picks one with the lowest weight that is locked. This will be compatible with old scripts. * if true, returns ALL the exits in the sub-table that lead to the particular room id that is the key in the main table, again those exit commands are the keys with a value being a "0" or "1" depending on whether the exit is unlocked or locked respectively. For the record, the original implementation of special exits was introduced in commit: e0ba28d4729f97f69cd91b178886ad6e7438d9a9 and that was supported by the addition of map format version 6. Locking of Special Exits was added in somewhere between: 19f8563b47454ca6c625c534384b1c7085351dfc and: 070912ea7c84414be2ddb86c371fc791c5718314 (which revised the map format to 11). Also: * use a couple of `const QString`s as templates in the `dlgRoomExit.cpp` file to remove 95 duplicated `QStringLiterals` from the read-only code segment of the compile object file. * add `const` where relevant to some `TRoom` methods. * work harder to ensure than when a special exit is deleted from a `TRoom` then elements that were related to it are also cleaned up. * prepare to save the new `TRoom` data structures in the next Mudlet map file format (21) when it is enabled. In the meantime a workaround to convert the in-game data to the current format is utilised for all current map formats Mudlet can currently use. This will impact a little on the save/loading speeds but that is the cost of simplifying the code that works with special exits elsewhere in the application. * revise and extend the error handling for the room special exit functions generally so that they confirm to our throwing an error on argument type issue (and reporting the faulty argument) and returning `nil` plus an error message for a run-time value problem. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2020-12-31 22:06:00 +00:00
if (mSaveVersion >= 21) {
ofs << pR->hidden;
Refactor: store special exits and their lock status separately (#4526) This will enable some simplification of code. During development it became clear that the Lua API `getSpecialExits(...)` function was a bit defective and did not behave as documented in the Wiki: it was only showing one special exit at random that led to a particular exit room in the (admittedly unlikely) event of there being more than one. It also used the special exit name/command as a key in a sub-table with the special exit lock status of that exit as a "0" or "1" string value. This PR repairs the above function by adding an optional boolean argument that: * if omitted or false, replicates the previous behaviour but if there is more than one special exit to the same room it always picks one with the lowest exit weight that is unlocked or if there is none it picks one with the lowest weight that is locked. This will be compatible with old scripts. * if true, returns ALL the exits in the sub-table that lead to the particular room id that is the key in the main table, again those exit commands are the keys with a value being a "0" or "1" depending on whether the exit is unlocked or locked respectively. For the record, the original implementation of special exits was introduced in commit: e0ba28d4729f97f69cd91b178886ad6e7438d9a9 and that was supported by the addition of map format version 6. Locking of Special Exits was added in somewhere between: 19f8563b47454ca6c625c534384b1c7085351dfc and: 070912ea7c84414be2ddb86c371fc791c5718314 (which revised the map format to 11). Also: * use a couple of `const QString`s as templates in the `dlgRoomExit.cpp` file to remove 95 duplicated `QStringLiterals` from the read-only code segment of the compile object file. * add `const` where relevant to some `TRoom` methods. * work harder to ensure than when a special exit is deleted from a `TRoom` then elements that were related to it are also cleaned up. * prepare to save the new `TRoom` data structures in the next Mudlet map file format (21) when it is enabled. In the meantime a workaround to convert the in-game data to the current format is utilised for all current map formats Mudlet can currently use. This will impact a little on the save/loading speeds but that is the cost of simplifying the code that works with special exits elsewhere in the application. * revise and extend the error handling for the room special exit functions generally so that they confirm to our throwing an error on argument type issue (and reporting the faulty argument) and returning `nil` plus an error message for a run-time value problem. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2020-12-31 22:06:00 +00:00
ofs << pR->getSpecialExits();
} else {
QMultiMap<int, QString> oldSpecialExits;
QMapIterator<QString, int> itSpecialExit(pR->getSpecialExits());
while (itSpecialExit.hasNext()) {
itSpecialExit.next();
oldSpecialExits.insert(itSpecialExit.value(), (pR->hasSpecialExitLock(itSpecialExit.key()) ? QLatin1Char('1') : QLatin1Char('0')) % itSpecialExit.key());
}
ofs << oldSpecialExits;
}
Enhance: add ability to set any glyph as a room symbol (#1543) This is a squashed down commit containing several commits with messages - this is the edited combination of all the messages: As well as being able to use any grapheme it is possible to use a short word as well as anything printable from any of the Unicode Multiple Planes; although the former will become smaller to fit within both the square and round room shapes on the 2D mapper. Adds controls to the profile preference to set the (preferred) font to use to set the room symbols from and a checkbox to only use that font. Additionally a sub-dialog can be brought up which lists the details of all the different symbols on the map - showing the Unicode codepoint(s) for each and showing how they would be rendered if only the selected font is used and if any font is permitted, along with a count of the usages and the rooms that use each one... A status icon is also displayed showing whether the symbol can be rendered entirely with the selected font (green tick), only by using glyphs from other fonts (yellow ! warning) or not with the current fonts on the system (red/white cross). This allows a user to make a sensible selection of a font to use or whether they will have a problem (and a replacement by the replacement character '�') for any symbols. Updates Lua setRoomChar and getRoomChar to handle the wider range of things that can be used. getRoomChar NOW allows for an existing character to be cleared with an empty string or a space as the char attribute. The map format version has been incremented to allow the data needed to be saved directly into the binary file format but failback code is in place that means that this feature can be carried in map and room user data instead for map format versions down to 17 - the current default is 18 and there is limited support to fail gracefully down to the 16 that Mudlet 2.1 uses (all the room letter markings that are not supported will become '?', and the font data will be lost, but the correct room character data will still be in the room user data.) Following review: * I replaced some colour specifications (white and transparent) with Qt constants. * Use the same inline function flushSymbolPixmapCache() to clear the map symbol pixmap cache in all places where it might be useful. * Simplify a couple of places where an if(...) {...} else {...} can be replaced with the (...) ? (...) : (...) operator. * Limit the number of room numbers displayed for each symbol in the new widget - to avoid complications where there are huge numbers of rooms using a symbol. * Replace a use of QTableWidget::clearContents() with QTableWidgets::setRowCount(0) as I was getting some odd, deep in the Qt internal library issues {Fatal Seg. Faults!} with the former, which I suspect, but could not prove, might have been a re-entrancy issue caused by the method containing it being called indirectly by an asynchronous SIGNAL/SLOT originating in the value change from the map symbol font selection QFontComboBox... Revised to NOT do scaling when drawing room symbols from cache: the previous QPainter::drawPixmap(...) performed a scaling operation to make the symbol pixmap fit the specified rectangle. This is the cause behind the poor rendering of text characters as the scaling undoes the benefits of anti-aliasing and takes time to do. This should be faster now because the pixmaps are generated at the size/resolution they are needed (though they do have to be thrown away and regenerated if the zoom or other sizing factors change) - they do however look better to me! Also: * merged (int) TRoom::xzoom and TRoom::yzoom into TRoom::xyzoom. * added the symbol scaling "fudge-factor" to the "Special Options" tab of the "Profile preferences" dialog - it may be helpful to artificially over-size (> 1.00) or under-size (< 1.00) the symbols in some situations. * uses the word symbol rather than just glyph/grapheme in some texts. Also modified 2D mapper "Symbol" tooltip to observe that more than one letter/symbol can be used (although they will be drawn smaller so that they still fit). Add tool-tips to profile preferences dialog for font controls (except for "fudge factor" control (with range x0.50 to x2.00 for scaling of symbol to test rectangle used to fit it into the room shape)... I have consistently mispelled chosen as choosen but I have fixed that now...! Also added tooltips to map glyph usage table/widget. WorkAround: try to force a specific US mirror for zziplib on AppVeyor CI AppVeyor is based in Vancouver, Canada so the nearest SF Mirror is in the US so this commit forces the use of that mirror for that library for the CI build process as an attempt to get around the repeated, intermittent failures to get that library from SourceForge (it is now the only item that needs to be downloaded from there for such builds)... Also adds another CI file that was not mentioned before in the qmake project file and thus did not show up in the Qt IDE. Following extensive discussions it has been made clear that introducing replacements for the lua [gs]etRoomChar(...) is not going to happen. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-03-28 14:06:12 +01:00
if (mSaveVersion >= 19) {
ofs << pR->mSymbol;
} else {
qint8 oldCharacterCode = 0;
if (!pR->mSymbol.isEmpty()) {
Enhance: add ability to set any glyph as a room symbol (#1543) This is a squashed down commit containing several commits with messages - this is the edited combination of all the messages: As well as being able to use any grapheme it is possible to use a short word as well as anything printable from any of the Unicode Multiple Planes; although the former will become smaller to fit within both the square and round room shapes on the 2D mapper. Adds controls to the profile preference to set the (preferred) font to use to set the room symbols from and a checkbox to only use that font. Additionally a sub-dialog can be brought up which lists the details of all the different symbols on the map - showing the Unicode codepoint(s) for each and showing how they would be rendered if only the selected font is used and if any font is permitted, along with a count of the usages and the rooms that use each one... A status icon is also displayed showing whether the symbol can be rendered entirely with the selected font (green tick), only by using glyphs from other fonts (yellow ! warning) or not with the current fonts on the system (red/white cross). This allows a user to make a sensible selection of a font to use or whether they will have a problem (and a replacement by the replacement character '�') for any symbols. Updates Lua setRoomChar and getRoomChar to handle the wider range of things that can be used. getRoomChar NOW allows for an existing character to be cleared with an empty string or a space as the char attribute. The map format version has been incremented to allow the data needed to be saved directly into the binary file format but failback code is in place that means that this feature can be carried in map and room user data instead for map format versions down to 17 - the current default is 18 and there is limited support to fail gracefully down to the 16 that Mudlet 2.1 uses (all the room letter markings that are not supported will become '?', and the font data will be lost, but the correct room character data will still be in the room user data.) Following review: * I replaced some colour specifications (white and transparent) with Qt constants. * Use the same inline function flushSymbolPixmapCache() to clear the map symbol pixmap cache in all places where it might be useful. * Simplify a couple of places where an if(...) {...} else {...} can be replaced with the (...) ? (...) : (...) operator. * Limit the number of room numbers displayed for each symbol in the new widget - to avoid complications where there are huge numbers of rooms using a symbol. * Replace a use of QTableWidget::clearContents() with QTableWidgets::setRowCount(0) as I was getting some odd, deep in the Qt internal library issues {Fatal Seg. Faults!} with the former, which I suspect, but could not prove, might have been a re-entrancy issue caused by the method containing it being called indirectly by an asynchronous SIGNAL/SLOT originating in the value change from the map symbol font selection QFontComboBox... Revised to NOT do scaling when drawing room symbols from cache: the previous QPainter::drawPixmap(...) performed a scaling operation to make the symbol pixmap fit the specified rectangle. This is the cause behind the poor rendering of text characters as the scaling undoes the benefits of anti-aliasing and takes time to do. This should be faster now because the pixmaps are generated at the size/resolution they are needed (though they do have to be thrown away and regenerated if the zoom or other sizing factors change) - they do however look better to me! Also: * merged (int) TRoom::xzoom and TRoom::yzoom into TRoom::xyzoom. * added the symbol scaling "fudge-factor" to the "Special Options" tab of the "Profile preferences" dialog - it may be helpful to artificially over-size (> 1.00) or under-size (< 1.00) the symbols in some situations. * uses the word symbol rather than just glyph/grapheme in some texts. Also modified 2D mapper "Symbol" tooltip to observe that more than one letter/symbol can be used (although they will be drawn smaller so that they still fit). Add tool-tips to profile preferences dialog for font controls (except for "fudge factor" control (with range x0.50 to x2.00 for scaling of symbol to test rectangle used to fit it into the room shape)... I have consistently mispelled chosen as choosen but I have fixed that now...! Also added tooltips to map glyph usage table/widget. WorkAround: try to force a specific US mirror for zziplib on AppVeyor CI AppVeyor is based in Vancouver, Canada so the nearest SF Mirror is in the US so this commit forces the use of that mirror for that library for the CI build process as an attempt to get around the repeated, intermittent failures to get that library from SourceForge (it is now the only item that needs to be downloaded from there for such builds)... Also adds another CI file that was not mentioned before in the qmake project file and thus did not show up in the Qt IDE. Following extensive discussions it has been made clear that introducing replacements for the lua [gs]etRoomChar(...) is not going to happen. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-03-28 14:06:12 +01:00
// There is something for a symbol
const QChar firstChar = pR->mSymbol.at(0);
Enhance: add ability to set any glyph as a room symbol (#1543) This is a squashed down commit containing several commits with messages - this is the edited combination of all the messages: As well as being able to use any grapheme it is possible to use a short word as well as anything printable from any of the Unicode Multiple Planes; although the former will become smaller to fit within both the square and round room shapes on the 2D mapper. Adds controls to the profile preference to set the (preferred) font to use to set the room symbols from and a checkbox to only use that font. Additionally a sub-dialog can be brought up which lists the details of all the different symbols on the map - showing the Unicode codepoint(s) for each and showing how they would be rendered if only the selected font is used and if any font is permitted, along with a count of the usages and the rooms that use each one... A status icon is also displayed showing whether the symbol can be rendered entirely with the selected font (green tick), only by using glyphs from other fonts (yellow ! warning) or not with the current fonts on the system (red/white cross). This allows a user to make a sensible selection of a font to use or whether they will have a problem (and a replacement by the replacement character '�') for any symbols. Updates Lua setRoomChar and getRoomChar to handle the wider range of things that can be used. getRoomChar NOW allows for an existing character to be cleared with an empty string or a space as the char attribute. The map format version has been incremented to allow the data needed to be saved directly into the binary file format but failback code is in place that means that this feature can be carried in map and room user data instead for map format versions down to 17 - the current default is 18 and there is limited support to fail gracefully down to the 16 that Mudlet 2.1 uses (all the room letter markings that are not supported will become '?', and the font data will be lost, but the correct room character data will still be in the room user data.) Following review: * I replaced some colour specifications (white and transparent) with Qt constants. * Use the same inline function flushSymbolPixmapCache() to clear the map symbol pixmap cache in all places where it might be useful. * Simplify a couple of places where an if(...) {...} else {...} can be replaced with the (...) ? (...) : (...) operator. * Limit the number of room numbers displayed for each symbol in the new widget - to avoid complications where there are huge numbers of rooms using a symbol. * Replace a use of QTableWidget::clearContents() with QTableWidgets::setRowCount(0) as I was getting some odd, deep in the Qt internal library issues {Fatal Seg. Faults!} with the former, which I suspect, but could not prove, might have been a re-entrancy issue caused by the method containing it being called indirectly by an asynchronous SIGNAL/SLOT originating in the value change from the map symbol font selection QFontComboBox... Revised to NOT do scaling when drawing room symbols from cache: the previous QPainter::drawPixmap(...) performed a scaling operation to make the symbol pixmap fit the specified rectangle. This is the cause behind the poor rendering of text characters as the scaling undoes the benefits of anti-aliasing and takes time to do. This should be faster now because the pixmaps are generated at the size/resolution they are needed (though they do have to be thrown away and regenerated if the zoom or other sizing factors change) - they do however look better to me! Also: * merged (int) TRoom::xzoom and TRoom::yzoom into TRoom::xyzoom. * added the symbol scaling "fudge-factor" to the "Special Options" tab of the "Profile preferences" dialog - it may be helpful to artificially over-size (> 1.00) or under-size (< 1.00) the symbols in some situations. * uses the word symbol rather than just glyph/grapheme in some texts. Also modified 2D mapper "Symbol" tooltip to observe that more than one letter/symbol can be used (although they will be drawn smaller so that they still fit). Add tool-tips to profile preferences dialog for font controls (except for "fudge factor" control (with range x0.50 to x2.00 for scaling of symbol to test rectangle used to fit it into the room shape)... I have consistently mispelled chosen as choosen but I have fixed that now...! Also added tooltips to map glyph usage table/widget. WorkAround: try to force a specific US mirror for zziplib on AppVeyor CI AppVeyor is based in Vancouver, Canada so the nearest SF Mirror is in the US so this commit forces the use of that mirror for that library for the CI build process as an attempt to get around the repeated, intermittent failures to get that library from SourceForge (it is now the only item that needs to be downloaded from there for such builds)... Also adds another CI file that was not mentioned before in the qmake project file and thus did not show up in the Qt IDE. Following extensive discussions it has been made clear that introducing replacements for the lua [gs]etRoomChar(...) is not going to happen. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-03-28 14:06:12 +01:00
if (pR->mSymbol.length() == 1 && firstChar.row() == 0 && firstChar.cell() > 32) {
// It is something that can be represented by the past unsigned short
oldCharacterCode = firstChar.toLatin1();
} else {
// Not representable - put in a '?' for older Mudlet
// versions that cannot display the character and will not
// parse the value placed in the room's user data:
oldCharacterCode = QChar('?').toLatin1();
}
}
ofs << oldCharacterCode;
}
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
if (mSaveVersion >= 21) {
ofs << pR->mSymbolColor;
}
Add per-room border color and thickness (#8758) #### Brief overview of PR changes/additions Adds per-room border color and thickness settings for the 2D mapper. Rooms can now have custom borders to visually distinguish them (e.g., indoor vs outdoor). New Lua functions: - `setRoomBorderColor(roomID, r, g, b[, a])` / `getRoomBorderColor()` / `clearRoomBorderColor()` - `setRoomBorderThickness(roomID, thickness)` / `getRoomBorderThickness()` / `clearRoomBorderThickness()` UI controls added to the room properties dialog. #### Motivation for adding to Mudlet [User request](https://discord.com/channels/283581582550237184/792073945922142259/1457314371184365569) to visually distinguish room types on maps, previously only possible in CMUD. #### Other info (issues closed, discussion etc) **Test case:** 1. Open a map with rooms 2. Run: `setRoomBorderColor(1, 255, 0, 0)` and `setRoomBorderThickness(1, 3)` 3. Room 1 should display with a thick red border 4. Run: `clearRoomBorderColor(1)` - border returns to global default color 5. Right-click a room → Properties → Border section allows setting color/thickness via UI https://github.com/user-attachments/assets/1261b84f-0ba1-4719-9f56-1870ba51e4d1 I looked into bumping the map format to 21 and storing the data natively, not using userdata - but then my map grew from 7.9MB to 8.7MB without me having changed any room's data at all! Just the extra structures, now empty, per room, added this might weight. In the end, going with a "sparse" storage solution of using room userdata is more space-efficient and less of an issue for backwards compatibility. --------- Co-authored-by: Vadim Peretokin <vadi2@users.noreply.github.com>
2026-01-12 19:16:27 +01:00
// Border properties are stored in userData (not binary stream) to avoid map bloat
if (pR->mBorderColor.isValid()) {
pR->userData.insert(ROOM_UI_BORDERCOLOR, pR->mBorderColor.name(QColor::HexArgb));
} else {
pR->userData.remove(ROOM_UI_BORDERCOLOR);
}
if (pR->mBorderThickness > 0) {
pR->userData.insert(ROOM_UI_BORDERTHICKNESS, QString::number(pR->mBorderThickness));
} else {
pR->userData.remove(ROOM_UI_BORDERTHICKNESS);
}
// Formats before 21 carry the hidden flag and symbol color - and
// formats before 19 the symbol - as user data fallbacks; use a local
// copy so that saving does not modify the live room's user data.
// TRoom::restore() strips each key again when loading a format that
// carries it, so none may appear in formats which store the value
// directly in the stream:
QMap<QString, QString> userData{pR->userData};
if (mSaveVersion < 21) {
if (pR->hidden) {
userData.insert(QLatin1String("system.fallback_hidden"), QLatin1String("true"));
}
if (pR->mSymbolColor.isValid()) {
userData.insert(QLatin1String("system.fallback_symbol_color"), pR->mSymbolColor.name());
}
}
if (mSaveVersion < 19 && !pR->mSymbol.isEmpty()) {
userData.insert(QLatin1String("system.fallback_symbol"), pR->mSymbol);
}
ofs << userData;
Enhance: improve code for room custom exit lines in 2D map (#2106) Changes the TRoom class to store the detail about the style of line as the Qt::PenStyle enum that is used when it is actually drawn (saves a few bytes per custom exit line)! Concurrently change the 2D map UI that adjusts this setting on both new custom exit lines being drawn and existing lines selected by the UI to separate the text used to describe the style from this value so that the text can be translated for other GUI languages without breaking the code. Enhance the control (a `QComboBox`) used for this so that it has icons with a visual representation of each style! Revise the Lua function `addCustomLine` to bring the error reporting up to current UI style - including detection some error conditions that were not previously reported (included whether there was the exit that the custom line was to be added to show). Also the target room who's location was used as the end-point for a single segment line was not being checked to confirm that it existed and was in the same area as the room that the exit line was being drawn from. Alternatively, when a table of tables of coordinate triplets {x, y, z} was provided there was previously no proper validation that they all existed and were numbers to be used as coordinates... I also discovered that TLuaInterpreter::dirToString was not producing the right `QString`s necessary for numeric arguments for the normal exit direction to work in the two lua functions that used it (`addCustomLine` and `setExitWeight`) I have corrected it and updated the callers of it to now return the right normal exit strings needed for each of them. To validate whether there is actually an exit in the direction that the lua addCustomLine function is told is a little complicated so I have added a `(bool) TRoom::hasExitOrSpecialExit(const QString&, const bool) const` method that does this so that addCustomLine can return a run-time error (nil + error message) if the given exit does not already exist. In some places in the TLuaInterpreter custom line functions and the `T2DMap::paintEvent()` method non-const method were being used to access the details of the custom exit lines - as this takes longer and runs the risk of changing the data when it should not be being changed I have switched to using the read only or constant `at(...)`/`value(...)` methods rather than the read/write or non-constant `operator[...]` method where practical. I have also made each custom exit line be drawn as a polyline rather than a series of single segments - this is more effiecent I think and it means that the dotted/dashed pattern effect "goes around" each corner rather than restarting on each segment which looks better IMHO - draw a multi-segment line and move one of the vertexes towards the end and you will see the differences. 8-) This should close #2095 ! Revised to make addCustomLine & setExitWeight not case sensitive for exit dir In fact have converted the TRoom custom exit line data members use a lower case key for "Normal" exit directions and go through all the places where those keys were used. Also make the change in the binary map data format 20 (and above). As it was convenient to do so, I have also changed it so that the custom line colour is stored as a `QColor` instead of a `QList<int>` of RGB components. The addCustomLine and setExitWeight lua functions now treat a wider range of strings as being for "Normal" exit directions in a case insensitive manner - there is a small possibility that this may clash with strings used for "Special" exits if they use a full English word for the exit direction (with or without hyphens for diagonal exits)... In testing the lua addCustomLine command I found that adding a new line to a room that did not previously have one produced a weirdly visible line that only showed up at some zoom levels and was very thin. It turned out that this is because there was not a call to TRoom::calcRoomDimensions() after adding the line and the TRoom::{min|max}_{x|y} members (which are updated by that) are used during the T2DMap::paintEvent(). Whilst I was working in this area of code I decided I could also provide the missing lua function `removeCustomLine`... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-11-17 20:46:02 +00:00
if (mSaveVersion >= 20) {
// Before version 20 stored the style as an Latin1 string, the color
// as a QList<int> for the RGB components and used UPPER case for
// the NORMAL exit direction keys...
ofs << pR->customLines;
ofs << pR->customLinesArrow;
ofs << pR->customLinesColor;
ofs << pR->customLinesStyle;
} else {
QMap<QString, QList<QPointF>> oldLinesData;
QMapIterator<QString, QList<QPointF>> itCustomLine(pR->customLines);
while (itCustomLine.hasNext()) {
itCustomLine.next();
const QString direction(itCustomLine.key());
Enhance: improve code for room custom exit lines in 2D map (#2106) Changes the TRoom class to store the detail about the style of line as the Qt::PenStyle enum that is used when it is actually drawn (saves a few bytes per custom exit line)! Concurrently change the 2D map UI that adjusts this setting on both new custom exit lines being drawn and existing lines selected by the UI to separate the text used to describe the style from this value so that the text can be translated for other GUI languages without breaking the code. Enhance the control (a `QComboBox`) used for this so that it has icons with a visual representation of each style! Revise the Lua function `addCustomLine` to bring the error reporting up to current UI style - including detection some error conditions that were not previously reported (included whether there was the exit that the custom line was to be added to show). Also the target room who's location was used as the end-point for a single segment line was not being checked to confirm that it existed and was in the same area as the room that the exit line was being drawn from. Alternatively, when a table of tables of coordinate triplets {x, y, z} was provided there was previously no proper validation that they all existed and were numbers to be used as coordinates... I also discovered that TLuaInterpreter::dirToString was not producing the right `QString`s necessary for numeric arguments for the normal exit direction to work in the two lua functions that used it (`addCustomLine` and `setExitWeight`) I have corrected it and updated the callers of it to now return the right normal exit strings needed for each of them. To validate whether there is actually an exit in the direction that the lua addCustomLine function is told is a little complicated so I have added a `(bool) TRoom::hasExitOrSpecialExit(const QString&, const bool) const` method that does this so that addCustomLine can return a run-time error (nil + error message) if the given exit does not already exist. In some places in the TLuaInterpreter custom line functions and the `T2DMap::paintEvent()` method non-const method were being used to access the details of the custom exit lines - as this takes longer and runs the risk of changing the data when it should not be being changed I have switched to using the read only or constant `at(...)`/`value(...)` methods rather than the read/write or non-constant `operator[...]` method where practical. I have also made each custom exit line be drawn as a polyline rather than a series of single segments - this is more effiecent I think and it means that the dotted/dashed pattern effect "goes around" each corner rather than restarting on each segment which looks better IMHO - draw a multi-segment line and move one of the vertexes towards the end and you will see the differences. 8-) This should close #2095 ! Revised to make addCustomLine & setExitWeight not case sensitive for exit dir In fact have converted the TRoom custom exit line data members use a lower case key for "Normal" exit directions and go through all the places where those keys were used. Also make the change in the binary map data format 20 (and above). As it was convenient to do so, I have also changed it so that the custom line colour is stored as a `QColor` instead of a `QList<int>` of RGB components. The addCustomLine and setExitWeight lua functions now treat a wider range of strings as being for "Normal" exit directions in a case insensitive manner - there is a small possibility that this may clash with strings used for "Special" exits if they use a full English word for the exit direction (with or without hyphens for diagonal exits)... In testing the lua addCustomLine command I found that adding a new line to a room that did not previously have one produced a weirdly visible line that only showed up at some zoom levels and was very thin. It turned out that this is because there was not a call to TRoom::calcRoomDimensions() after adding the line and the TRoom::{min|max}_{x|y} members (which are updated by that) are used during the T2DMap::paintEvent(). Whilst I was working in this area of code I decided I could also provide the missing lua function `removeCustomLine`... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-11-17 20:46:02 +00:00
if (direction == QLatin1String("n") || direction == QLatin1String("e") || direction == QLatin1String("s") || direction == QLatin1String("w") || direction == QLatin1String("up")
|| direction == QLatin1String("down") || direction == QLatin1String("ne") || direction == QLatin1String("se") || direction == QLatin1String("sw")
|| direction == QLatin1String("nw") || direction == QLatin1String("in") || direction == QLatin1String("out")) {
oldLinesData.insert(itCustomLine.key().toUpper(), itCustomLine.value());
} else {
oldLinesData.insert(itCustomLine.key(), itCustomLine.value());
}
}
ofs << oldLinesData;
QMap<QString, bool> oldLinesArrowData;
QMapIterator<QString, bool> itCustomLineArrow(pR->customLinesArrow);
while (itCustomLineArrow.hasNext()) {
itCustomLineArrow.next();
const QString direction(itCustomLineArrow.key());
Enhance: improve code for room custom exit lines in 2D map (#2106) Changes the TRoom class to store the detail about the style of line as the Qt::PenStyle enum that is used when it is actually drawn (saves a few bytes per custom exit line)! Concurrently change the 2D map UI that adjusts this setting on both new custom exit lines being drawn and existing lines selected by the UI to separate the text used to describe the style from this value so that the text can be translated for other GUI languages without breaking the code. Enhance the control (a `QComboBox`) used for this so that it has icons with a visual representation of each style! Revise the Lua function `addCustomLine` to bring the error reporting up to current UI style - including detection some error conditions that were not previously reported (included whether there was the exit that the custom line was to be added to show). Also the target room who's location was used as the end-point for a single segment line was not being checked to confirm that it existed and was in the same area as the room that the exit line was being drawn from. Alternatively, when a table of tables of coordinate triplets {x, y, z} was provided there was previously no proper validation that they all existed and were numbers to be used as coordinates... I also discovered that TLuaInterpreter::dirToString was not producing the right `QString`s necessary for numeric arguments for the normal exit direction to work in the two lua functions that used it (`addCustomLine` and `setExitWeight`) I have corrected it and updated the callers of it to now return the right normal exit strings needed for each of them. To validate whether there is actually an exit in the direction that the lua addCustomLine function is told is a little complicated so I have added a `(bool) TRoom::hasExitOrSpecialExit(const QString&, const bool) const` method that does this so that addCustomLine can return a run-time error (nil + error message) if the given exit does not already exist. In some places in the TLuaInterpreter custom line functions and the `T2DMap::paintEvent()` method non-const method were being used to access the details of the custom exit lines - as this takes longer and runs the risk of changing the data when it should not be being changed I have switched to using the read only or constant `at(...)`/`value(...)` methods rather than the read/write or non-constant `operator[...]` method where practical. I have also made each custom exit line be drawn as a polyline rather than a series of single segments - this is more effiecent I think and it means that the dotted/dashed pattern effect "goes around" each corner rather than restarting on each segment which looks better IMHO - draw a multi-segment line and move one of the vertexes towards the end and you will see the differences. 8-) This should close #2095 ! Revised to make addCustomLine & setExitWeight not case sensitive for exit dir In fact have converted the TRoom custom exit line data members use a lower case key for "Normal" exit directions and go through all the places where those keys were used. Also make the change in the binary map data format 20 (and above). As it was convenient to do so, I have also changed it so that the custom line colour is stored as a `QColor` instead of a `QList<int>` of RGB components. The addCustomLine and setExitWeight lua functions now treat a wider range of strings as being for "Normal" exit directions in a case insensitive manner - there is a small possibility that this may clash with strings used for "Special" exits if they use a full English word for the exit direction (with or without hyphens for diagonal exits)... In testing the lua addCustomLine command I found that adding a new line to a room that did not previously have one produced a weirdly visible line that only showed up at some zoom levels and was very thin. It turned out that this is because there was not a call to TRoom::calcRoomDimensions() after adding the line and the TRoom::{min|max}_{x|y} members (which are updated by that) are used during the T2DMap::paintEvent(). Whilst I was working in this area of code I decided I could also provide the missing lua function `removeCustomLine`... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-11-17 20:46:02 +00:00
if (direction == QLatin1String("n") || direction == QLatin1String("e") || direction == QLatin1String("s") || direction == QLatin1String("w") || direction == QLatin1String("up")
|| direction == QLatin1String("down") || direction == QLatin1String("ne") || direction == QLatin1String("se") || direction == QLatin1String("sw")
|| direction == QLatin1String("nw") || direction == QLatin1String("in") || direction == QLatin1String("out")) {
oldLinesArrowData.insert(itCustomLineArrow.key().toUpper(), itCustomLineArrow.value());
} else {
oldLinesArrowData.insert(itCustomLineArrow.key(), itCustomLineArrow.value());
}
}
ofs << oldLinesArrowData;
QMap<QString, QList<int>> oldLinesColorData;
QMapIterator<QString, QColor> itCustomLineColor(pR->customLinesColor);
while (itCustomLineColor.hasNext()) {
Enhance: improve code for room custom exit lines in 2D map (#2106) Changes the TRoom class to store the detail about the style of line as the Qt::PenStyle enum that is used when it is actually drawn (saves a few bytes per custom exit line)! Concurrently change the 2D map UI that adjusts this setting on both new custom exit lines being drawn and existing lines selected by the UI to separate the text used to describe the style from this value so that the text can be translated for other GUI languages without breaking the code. Enhance the control (a `QComboBox`) used for this so that it has icons with a visual representation of each style! Revise the Lua function `addCustomLine` to bring the error reporting up to current UI style - including detection some error conditions that were not previously reported (included whether there was the exit that the custom line was to be added to show). Also the target room who's location was used as the end-point for a single segment line was not being checked to confirm that it existed and was in the same area as the room that the exit line was being drawn from. Alternatively, when a table of tables of coordinate triplets {x, y, z} was provided there was previously no proper validation that they all existed and were numbers to be used as coordinates... I also discovered that TLuaInterpreter::dirToString was not producing the right `QString`s necessary for numeric arguments for the normal exit direction to work in the two lua functions that used it (`addCustomLine` and `setExitWeight`) I have corrected it and updated the callers of it to now return the right normal exit strings needed for each of them. To validate whether there is actually an exit in the direction that the lua addCustomLine function is told is a little complicated so I have added a `(bool) TRoom::hasExitOrSpecialExit(const QString&, const bool) const` method that does this so that addCustomLine can return a run-time error (nil + error message) if the given exit does not already exist. In some places in the TLuaInterpreter custom line functions and the `T2DMap::paintEvent()` method non-const method were being used to access the details of the custom exit lines - as this takes longer and runs the risk of changing the data when it should not be being changed I have switched to using the read only or constant `at(...)`/`value(...)` methods rather than the read/write or non-constant `operator[...]` method where practical. I have also made each custom exit line be drawn as a polyline rather than a series of single segments - this is more effiecent I think and it means that the dotted/dashed pattern effect "goes around" each corner rather than restarting on each segment which looks better IMHO - draw a multi-segment line and move one of the vertexes towards the end and you will see the differences. 8-) This should close #2095 ! Revised to make addCustomLine & setExitWeight not case sensitive for exit dir In fact have converted the TRoom custom exit line data members use a lower case key for "Normal" exit directions and go through all the places where those keys were used. Also make the change in the binary map data format 20 (and above). As it was convenient to do so, I have also changed it so that the custom line colour is stored as a `QColor` instead of a `QList<int>` of RGB components. The addCustomLine and setExitWeight lua functions now treat a wider range of strings as being for "Normal" exit directions in a case insensitive manner - there is a small possibility that this may clash with strings used for "Special" exits if they use a full English word for the exit direction (with or without hyphens for diagonal exits)... In testing the lua addCustomLine command I found that adding a new line to a room that did not previously have one produced a weirdly visible line that only showed up at some zoom levels and was very thin. It turned out that this is because there was not a call to TRoom::calcRoomDimensions() after adding the line and the TRoom::{min|max}_{x|y} members (which are updated by that) are used during the T2DMap::paintEvent(). Whilst I was working in this area of code I decided I could also provide the missing lua function `removeCustomLine`... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-11-17 20:46:02 +00:00
itCustomLineColor.next();
const QString direction(itCustomLineColor.key());
Enhance: improve code for room custom exit lines in 2D map (#2106) Changes the TRoom class to store the detail about the style of line as the Qt::PenStyle enum that is used when it is actually drawn (saves a few bytes per custom exit line)! Concurrently change the 2D map UI that adjusts this setting on both new custom exit lines being drawn and existing lines selected by the UI to separate the text used to describe the style from this value so that the text can be translated for other GUI languages without breaking the code. Enhance the control (a `QComboBox`) used for this so that it has icons with a visual representation of each style! Revise the Lua function `addCustomLine` to bring the error reporting up to current UI style - including detection some error conditions that were not previously reported (included whether there was the exit that the custom line was to be added to show). Also the target room who's location was used as the end-point for a single segment line was not being checked to confirm that it existed and was in the same area as the room that the exit line was being drawn from. Alternatively, when a table of tables of coordinate triplets {x, y, z} was provided there was previously no proper validation that they all existed and were numbers to be used as coordinates... I also discovered that TLuaInterpreter::dirToString was not producing the right `QString`s necessary for numeric arguments for the normal exit direction to work in the two lua functions that used it (`addCustomLine` and `setExitWeight`) I have corrected it and updated the callers of it to now return the right normal exit strings needed for each of them. To validate whether there is actually an exit in the direction that the lua addCustomLine function is told is a little complicated so I have added a `(bool) TRoom::hasExitOrSpecialExit(const QString&, const bool) const` method that does this so that addCustomLine can return a run-time error (nil + error message) if the given exit does not already exist. In some places in the TLuaInterpreter custom line functions and the `T2DMap::paintEvent()` method non-const method were being used to access the details of the custom exit lines - as this takes longer and runs the risk of changing the data when it should not be being changed I have switched to using the read only or constant `at(...)`/`value(...)` methods rather than the read/write or non-constant `operator[...]` method where practical. I have also made each custom exit line be drawn as a polyline rather than a series of single segments - this is more effiecent I think and it means that the dotted/dashed pattern effect "goes around" each corner rather than restarting on each segment which looks better IMHO - draw a multi-segment line and move one of the vertexes towards the end and you will see the differences. 8-) This should close #2095 ! Revised to make addCustomLine & setExitWeight not case sensitive for exit dir In fact have converted the TRoom custom exit line data members use a lower case key for "Normal" exit directions and go through all the places where those keys were used. Also make the change in the binary map data format 20 (and above). As it was convenient to do so, I have also changed it so that the custom line colour is stored as a `QColor` instead of a `QList<int>` of RGB components. The addCustomLine and setExitWeight lua functions now treat a wider range of strings as being for "Normal" exit directions in a case insensitive manner - there is a small possibility that this may clash with strings used for "Special" exits if they use a full English word for the exit direction (with or without hyphens for diagonal exits)... In testing the lua addCustomLine command I found that adding a new line to a room that did not previously have one produced a weirdly visible line that only showed up at some zoom levels and was very thin. It turned out that this is because there was not a call to TRoom::calcRoomDimensions() after adding the line and the TRoom::{min|max}_{x|y} members (which are updated by that) are used during the T2DMap::paintEvent(). Whilst I was working in this area of code I decided I could also provide the missing lua function `removeCustomLine`... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-11-17 20:46:02 +00:00
QList<int> colorComponents;
colorComponents << itCustomLineColor.value().red() << itCustomLineColor.value().green() << itCustomLineColor.value().blue();
if (direction == QLatin1String("n") || direction == QLatin1String("e") || direction == QLatin1String("s") || direction == QLatin1String("w") || direction == QLatin1String("up")
|| direction == QLatin1String("down") || direction == QLatin1String("ne") || direction == QLatin1String("se") || direction == QLatin1String("sw")
|| direction == QLatin1String("nw") || direction == QLatin1String("in") || direction == QLatin1String("out")) {
oldLinesColorData.insert(itCustomLineColor.key().toUpper(), colorComponents);
} else {
oldLinesColorData.insert(itCustomLineColor.key(), colorComponents);
}
}
ofs << oldLinesColorData;
QMap<QString, QString> oldLineStyleData;
QMapIterator<QString, Qt::PenStyle> itCustomLineStyle(pR->customLinesStyle);
while (itCustomLineStyle.hasNext()) {
itCustomLineStyle.next();
QString direction(itCustomLineStyle.key());
if (direction == QLatin1String("n") || direction == QLatin1String("e") || direction == QLatin1String("s") || direction == QLatin1String("w") || direction == QLatin1String("up")
|| direction == QLatin1String("down") || direction == QLatin1String("ne") || direction == QLatin1String("se") || direction == QLatin1String("sw")
|| direction == QLatin1String("nw") || direction == QLatin1String("in") || direction == QLatin1String("out")) {
direction = direction.toUpper();
}
switch (itCustomLineStyle.value()) {
case Qt::DotLine:
oldLineStyleData.insert(direction, QLatin1String("dot line"));
break;
case Qt::DashLine:
oldLineStyleData.insert(direction, QLatin1String("dash line"));
break;
case Qt::DashDotLine:
oldLineStyleData.insert(direction, QLatin1String("dash dot line"));
break;
case Qt::DashDotDotLine:
oldLineStyleData.insert(direction, QLatin1String("dash dot dot line"));
break;
case Qt::SolidLine:
[[fallthrough]];
Enhance: improve code for room custom exit lines in 2D map (#2106) Changes the TRoom class to store the detail about the style of line as the Qt::PenStyle enum that is used when it is actually drawn (saves a few bytes per custom exit line)! Concurrently change the 2D map UI that adjusts this setting on both new custom exit lines being drawn and existing lines selected by the UI to separate the text used to describe the style from this value so that the text can be translated for other GUI languages without breaking the code. Enhance the control (a `QComboBox`) used for this so that it has icons with a visual representation of each style! Revise the Lua function `addCustomLine` to bring the error reporting up to current UI style - including detection some error conditions that were not previously reported (included whether there was the exit that the custom line was to be added to show). Also the target room who's location was used as the end-point for a single segment line was not being checked to confirm that it existed and was in the same area as the room that the exit line was being drawn from. Alternatively, when a table of tables of coordinate triplets {x, y, z} was provided there was previously no proper validation that they all existed and were numbers to be used as coordinates... I also discovered that TLuaInterpreter::dirToString was not producing the right `QString`s necessary for numeric arguments for the normal exit direction to work in the two lua functions that used it (`addCustomLine` and `setExitWeight`) I have corrected it and updated the callers of it to now return the right normal exit strings needed for each of them. To validate whether there is actually an exit in the direction that the lua addCustomLine function is told is a little complicated so I have added a `(bool) TRoom::hasExitOrSpecialExit(const QString&, const bool) const` method that does this so that addCustomLine can return a run-time error (nil + error message) if the given exit does not already exist. In some places in the TLuaInterpreter custom line functions and the `T2DMap::paintEvent()` method non-const method were being used to access the details of the custom exit lines - as this takes longer and runs the risk of changing the data when it should not be being changed I have switched to using the read only or constant `at(...)`/`value(...)` methods rather than the read/write or non-constant `operator[...]` method where practical. I have also made each custom exit line be drawn as a polyline rather than a series of single segments - this is more effiecent I think and it means that the dotted/dashed pattern effect "goes around" each corner rather than restarting on each segment which looks better IMHO - draw a multi-segment line and move one of the vertexes towards the end and you will see the differences. 8-) This should close #2095 ! Revised to make addCustomLine & setExitWeight not case sensitive for exit dir In fact have converted the TRoom custom exit line data members use a lower case key for "Normal" exit directions and go through all the places where those keys were used. Also make the change in the binary map data format 20 (and above). As it was convenient to do so, I have also changed it so that the custom line colour is stored as a `QColor` instead of a `QList<int>` of RGB components. The addCustomLine and setExitWeight lua functions now treat a wider range of strings as being for "Normal" exit directions in a case insensitive manner - there is a small possibility that this may clash with strings used for "Special" exits if they use a full English word for the exit direction (with or without hyphens for diagonal exits)... In testing the lua addCustomLine command I found that adding a new line to a room that did not previously have one produced a weirdly visible line that only showed up at some zoom levels and was very thin. It turned out that this is because there was not a call to TRoom::calcRoomDimensions() after adding the line and the TRoom::{min|max}_{x|y} members (which are updated by that) are used during the T2DMap::paintEvent(). Whilst I was working in this area of code I decided I could also provide the missing lua function `removeCustomLine`... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-11-17 20:46:02 +00:00
default:
oldLineStyleData.insert(direction, QLatin1String("solid line"));
}
}
ofs << oldLineStyleData;
}
Refactor: store special exits and their lock status separately (#4526) This will enable some simplification of code. During development it became clear that the Lua API `getSpecialExits(...)` function was a bit defective and did not behave as documented in the Wiki: it was only showing one special exit at random that led to a particular exit room in the (admittedly unlikely) event of there being more than one. It also used the special exit name/command as a key in a sub-table with the special exit lock status of that exit as a "0" or "1" string value. This PR repairs the above function by adding an optional boolean argument that: * if omitted or false, replicates the previous behaviour but if there is more than one special exit to the same room it always picks one with the lowest exit weight that is unlocked or if there is none it picks one with the lowest weight that is locked. This will be compatible with old scripts. * if true, returns ALL the exits in the sub-table that lead to the particular room id that is the key in the main table, again those exit commands are the keys with a value being a "0" or "1" depending on whether the exit is unlocked or locked respectively. For the record, the original implementation of special exits was introduced in commit: e0ba28d4729f97f69cd91b178886ad6e7438d9a9 and that was supported by the addition of map format version 6. Locking of Special Exits was added in somewhere between: 19f8563b47454ca6c625c534384b1c7085351dfc and: 070912ea7c84414be2ddb86c371fc791c5718314 (which revised the map format to 11). Also: * use a couple of `const QString`s as templates in the `dlgRoomExit.cpp` file to remove 95 duplicated `QStringLiterals` from the read-only code segment of the compile object file. * add `const` where relevant to some `TRoom` methods. * work harder to ensure than when a special exit is deleted from a `TRoom` then elements that were related to it are also cleaned up. * prepare to save the new `TRoom` data structures in the next Mudlet map file format (21) when it is enabled. In the meantime a workaround to convert the in-game data to the current format is utilised for all current map formats Mudlet can currently use. This will impact a little on the save/loading speeds but that is the cost of simplifying the code that works with special exits elsewhere in the application. * revise and extend the error handling for the room special exit functions generally so that they confirm to our throwing an error on argument type issue (and reporting the faulty argument) and returning `nil` plus an error message for a run-time value problem. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2020-12-31 22:06:00 +00:00
if (mSaveVersion >= 21) {
ofs << pR->getSpecialExitLocks();
}
2013-03-22 12:47:58 +01:00
ofs << pR->exitLocks;
ofs << pR->exitStubs;
2013-05-26 11:47:15 +02:00
ofs << pR->getExitWeights();
2013-03-22 12:47:58 +01:00
ofs << pR->doors;
2010-08-25 00:41:43 +02:00
}
// reset to the old map version
mSaveVersion = oldSaveVersion;
2010-08-25 00:41:43 +02:00
return true;
}
2021-04-02 19:10:16 +01:00
// file is expected to be linked to a file name but not be opened; ifs is not
// expected to be linked to any IODevice. On success file will be opened and
// ifs will be part way through it (has read the first 4 bytes which encode the
// map file version). On failure both will be in the same states as initial one:
bool TMap::validatePotentialMapFile(QFile& file, QDataStream& ifs)
{
int version = 0;
if (!file.open(QFile::ReadOnly)) {
const QString errMsg = tr(R"([ ERROR ] - Unable to open map file for reading: "%1"!)").arg(file.fileName());
2021-04-02 19:10:16 +01:00
appendErrorMsg(errMsg, false);
postMessage(errMsg);
return false;
}
ifs.setDevice(&file);
// Is the RUN-TIME version of the Qt libraries equal to or more than
// Qt 5.13.0? Then force things to use the backwards compatible format
// - for us - of Qt 5.12.0 - this is needed because the way that the
// QFont class is stored in a binary format has changed at 5.13 and it
// causes crashes when a new version of the Qt libraries tries to read
// the older format:
if (mudlet::scmRunTimeQtVersion >= QVersionNumber(5, 13, 0)) {
// 18 is the enum value corresponding to QDataStream::Qt_5_12 which
// we want to force to be used but we cannot use the enum directly
// because it will not be defined in older versions of the Qt
// library when the code is compilated:
ifs.setVersion(mudlet::scmQDataStreamFormat_5_12);
}
ifs >> version;
if ((version < 1) || (version > 127)) {
const QString errMsg = tr("[ ALERT ] - File does not seem to be a Mudlet Map file. The part that indicates\n"
"its format version seems to be \"%1\" and that doesn't make sense. The file is:\n"
2021-04-02 19:10:16 +01:00
"\"%2\".")
.arg(version)
.arg(file.fileName());
appendErrorMsgWithNoLf(errMsg);
postMessage(errMsg);
const QString infoMsg = tr("[ INFO ] - Ignoring this unlikely map file.");
2021-04-02 19:10:16 +01:00
appendErrorMsgWithNoLf(infoMsg);
postMessage(infoMsg);
ifs.setDevice(nullptr);
file.close();
return false;
}
if (version > mMaxVersion) {
const QString errMsg = tr("[ ALERT ] - Map file is too new. Its format version \"%1\" is higher than this version of\n"
"Mudlet can handle (%2)! The file is:\n\"%3\".")
2021-04-02 19:10:16 +01:00
.arg(version)
.arg(mMaxVersion)
.arg(file.fileName());
appendErrorMsgWithNoLf(errMsg);
postMessage(errMsg);
const QString infoMsg = tr("[ INFO ] - You will need to update your Mudlet to read the map file.");
2021-04-02 19:10:16 +01:00
appendErrorMsgWithNoLf(infoMsg);
postMessage(infoMsg);
ifs.setDevice(nullptr);
file.close();
return false;
}
if (version < 4) {
const QString alertMsg = tr("[ ALERT ] - Map file is really old. Its format version \"%1\" is so ancient that\n"
2021-04-02 19:10:16 +01:00
"this version of Mudlet may not gain enough information from\n"
"it but it will try! The file is: \"%2\".")
2021-04-02 19:10:16 +01:00
.arg(version)
.arg(file.fileName());
appendErrorMsgWithNoLf(alertMsg, false);
postMessage(alertMsg);
const QString infoMsg = tr("[ INFO ] - You might wish to donate THIS map file to the Mudlet Museum!\n"
2021-04-02 19:10:16 +01:00
"There is so much data that it DOES NOT have that you could be\n"
"better off starting again...");
appendErrorMsgWithNoLf(infoMsg, false);
postMessage(infoMsg);
} else {
// Less than (but not less than 4) or equal to default version
const QString infoMsg = tr("[ INFO ] - Reading map. Format version: %1. File:\n"
2021-04-02 19:10:16 +01:00
"\"%2\",\n"
"please wait...")
.arg(version)
.arg(file.fileName());
appendErrorMsg(tr(R"([ INFO ] - Reading map. Format version: %1. File: "%2".)").arg(version).arg(file.fileName()), false);
2021-04-02 19:10:16 +01:00
postMessage(infoMsg);
}
mVersion = version;
mSaveVersion = mDefaultVersion; // Make the save version the default one - unless the user intervenes
return true;
}
bool TMap::restore(QString location)
2010-08-25 00:41:43 +02:00
{
fix: profile close during a map operation, Discord presence truncation, and interrupting ttsSpeak() (#9686) #### Brief overview of PR changes/additions - Closing a profile no longer frees the map out from under a running import, export or download. `TMap` counts the operations that pump `qApp->processEvents()`, and `mudlet::closeHost()` - which one of those pumps is what delivers it - stops the operation and destroys the `Host` once it has unwound, instead of half way through it. - Discord presence fields keep their last character and are only ever cut between characters: each buffer is now the documented limit plus room for its terminator, and a new `utils::copyUtf8String()` walks the cut back to a character boundary. - An interrupting `ttsSpeak()` announces the utterance it starts, and the `Ready` an engine reports for the utterance it cut off no longer drains `ttsQueue()` over the top of the one the script asked for. #### Motivation for adding to Mudlet Each is a filed defect, and each was reproduced before it was fixed. The map one is a use-after-free: ASan reports `heap-use-after-free` inside `TMap::readJsonMapFile()`, freed by `~TMap` <- `~Host` <- `HostManager::deleteHost` <- `mudlet::closeHost` delivered by the import's own `processEvents()`. The Discord one is worse than one field looking wrong: a single over-long non-ASCII field makes the whole `SET_ACTIVITY` payload undecodable, so the entire presence update is discarded - the fake Discord client recorded exactly that. The TTS one silently drops speech: `ttsQueue()` plus an interrupting `ttsSpeak()` speaks the queued line and never speaks the requested one. #### Other info (issues closed, discussion etc) Closes #9520, closes #9634, closes #9659. `MapCloseDuringImportTest` stages the close through `mudlet::slot_closeProfileByName()` and lets the map operation's own pump deliver it; the functional tests build with ASan, so the pre-fix run is a sanitizer report rather than an inference. `TtsInterruptingSpeakTest` hands `ttsStateChanged()` the `Ready` a real engine sends, which Qt's mock engine never does - the mock-visible half is pinned in `Media_spec.lua`, where the two specs that recorded the old behaviour are updated. `Discord_spec.lua` gains four end-to-end specs against `CI/discord-ipc-fixture.py` asserting that the captured frame still decodes as JSON and that a field is cut on a character boundary, and `DiscordTest.cpp` covers the same at unit level. Every new or changed test was confirmed to fail without its fix. Two things deliberately left alone, both older than this PR: `Host::requestClose()` still runs nested inside the map operation's pump (it saves the profile there), and an XML import or a map download has no cancel to poll, so a close waits for it rather than stopping it. **Test case:** Export a large map with `exportJsonMap()` and close the profile's tab while it runs; then `setDiscordDetail(string.rep("ä", 65))` and confirm the presence still updates; then `ttsQueue("queued line") ttsSpeak("first")` followed immediately by `ttsSpeak("second")` and confirm "second" is what gets spoken. Assisted-by: Claude:claude-opus-5
2026-08-07 06:10:42 +02:00
const MapOperationScope operationScope(this);
2021-04-02 19:10:16 +01:00
qDebug().noquote().nospace() << "TMap::restore(\"" << location << "\") INFO: restoring map of Profile: \"" << mProfileName << "\" URL: " << mpHost->getUrl();
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
Backport: merge ten commits room "entrance" code from "release_30" to "development" branches, Commit 01 of 10 originally entitled: "fix for keeping reverse area exit map in sync with exit creation, adding, and deletion" Conflicts resolved in: src/TRoom.h Commit 02 of 10 originally entitled: "bug fix for entranceMap having reversed key and value" Conflicts resolved in: src/TRoomDB.cpp Commit 03 of 10 originally entitled: "removal of entranceMap cleanup" Conflicts resolved in: src/TRoomDB.cpp Commit 04 of 10 originally entitled: "BugFix: prevent crash in dlgRoomExits::initExits() on missing exit" Code deficiencies that remove rooms without properly updating connected rooms were causing segmentation faults because this method - perhaps foolishly - expected a room to exist when another room had an exit Id to the room given. This commit corrects any faulty normal exits now by resetting them to the no exit -1 value. Commit 05 of 10 originally entitled: "Fixup: prevent unneeded TRoom::setExit() calls from dlgRoomExits class" Each individual call to TRoom::setExit((int)exitRoomId,(int)directionCode) from dlgRoomExit::save() creates additional entries in TRoom::entranceMap even for non-exit directions. To reduce (but unfortunately not eliminate) the number of duplicates change the save() code to only use setExit() when a difference between the current and saved exit room numbers is found. Commit 06 of 10 originally entitled: "Fixup: clear TRoomDB::entranceMap on map clearance" Obvious but was missing. Commit 07 of 10 originally entitled: "Fixup: add getAllRoomEntrances() to Lua command set" Though suitable for release code this was added to help with debugging. This was what enabled me to spot the problems that the previous pair of commits ameliorates. This currently only reports the rooms that have exit(s) that lead to the given room Id. It is anticipated that there will be a future revision to report the particular direction(s) from the given room(s) are the one(s) that lead to the room, using a second argument that will be a boolean true to trigger that behavior (the absence of, or a false, second argument would then cause the result that this code produces.) Conflicts resolved in: src/TLuaInterpreter.cpp src/TLuaInterpreter.h Commit 08 of 10 originally entitled: "Fixup: add debugging output to TRoomDB::updateEntranceMap(TRoom *)" Set a break point in the method and change the static bool showDebug to dis-/en-able output... Conflicts resolved in: src/TRoomDB.cpp Commit 09 of 10 originally entitled: "FixEnhance: fix entranceMap maintenance, bulk room deletion & map loading" Previously we were not removing entries from the entranceMap involving the value (a room that the room Id that was a key had an entrance FROM) when a route was changed. There is a performance cost in ensuring the data is kept correctly - there may be a modest gain by storing the entrance data within each TRoom class instance rather than a central database in TRoomDB... Deletion of multiple rooms and map loading can be done more efficiently if we skip some redundant steps. Also added/revised some timing code to measure things. Conflicts resolved in: src/TRoomDB.cpp src/TRoomDB.h Commit 10 of 10 originally entitled: "BugFix: Some previous coding errors" * T2DMap::slot_setArea(): used a uint where I should have used an int as a method I called can return a -1 in some cases. * TArea::getAreaExitRoomData(): a qWarning() in a debugging line I had used the wrong type (%1,%2,...) of format string argument characters when I should of used (%i or %s)... * (bool)TArea::mIsDirty: was put in wrong block of lines in header Conflicts resolved in: src/TArea.h Further conflicts resolved which were brought about by later re-basing before posting code out to world: src/dlgRoomExits.cpp Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-08-15 22:15:39 +01:00
QElapsedTimer _time;
_time.start();
QString folder;
QStringList entries;
if (location.isEmpty()) {
folder = mudlet::getMudletPath(enums::profileMapsPath, mProfileName);
const QDir dir(folder);
2021-04-02 19:10:16 +01:00
QStringList filters;
filters << qsl("*.[dD][aA][tT]");
filters << qsl("*.[jJ][sS][oO][nN]");
2021-04-02 19:10:16 +01:00
entries = dir.entryList(filters, QDir::Files, QDir::Time);
}
2010-08-25 00:41:43 +02:00
bool canRestore = true;
if (entries.empty() && location.isEmpty()) {
canRestore = false;
}
2021-04-02 19:10:16 +01:00
QDataStream ifs;
QFile file;
if (canRestore && (!entries.empty() || !location.isEmpty())) {
2021-04-02 19:10:16 +01:00
// We get to here if there is one or more entries OR location is
// supplied - if the latter then there is only one file to consider but
// if the former we may have to check more than one to find a valid
// map file:
bool foundValidFile = false;
if (location.isEmpty()) {
// Look through the entries:
QStringListIterator itFileName(entries);
auto fileName = qsl("%1/%2").arg(folder, itFileName.next());
if (!fileName.endsWith(qsl(".json"), Qt::CaseInsensitive)) {
2021-04-02 19:10:16 +01:00
file.setFileName(fileName);
if (validatePotentialMapFile(file, ifs)) {
foundValidFile = true;
}
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
2021-04-02 19:10:16 +01:00
} else {
if (auto [isOk, message] = readJsonMapFile(fileName, true); !isOk) {
// Failed to read the JSON file
const QString errMsg = tr("[ ALERT ] - Failed to load a Mudlet JSON Map file, reason:\n"
2021-04-02 19:10:16 +01:00
"%1; the file is:\n"
"\"%2\".")
.arg(message, fileName);
appendErrorMsgWithNoLf(errMsg);
postMessage(errMsg);
const QString infoMsg = tr("[ INFO ] - Ignoring this map file.");
2021-04-02 19:10:16 +01:00
appendErrorMsgWithNoLf(infoMsg);
postMessage(infoMsg);
} else {
// immediately leave on success:
return true;
}
}
2021-04-02 19:10:16 +01:00
// Allow for somethings to be updated - especially on Windows?
qApp->processEvents();
2021-05-11 21:26:47 +02:00
} else {
file.setFileName(location);
if (validatePotentialMapFile(file, ifs)) {
foundValidFile = true;
}
2021-04-02 19:10:16 +01:00
}
if (!foundValidFile) {
2010-08-25 00:41:43 +02:00
canRestore = false;
}
} else if (canRestore && !location.isEmpty()) {
2021-04-02 19:10:16 +01:00
file.setFileName(location);
canRestore = validatePotentialMapFile(file, ifs);
}
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
2021-04-02 19:10:16 +01:00
if (canRestore) {
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
// As all but the room reading have version checks the fact that sub-4
// files will still be parsed despite canRestore being false is probably OK
if (mVersion >= 4) {
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
ifs >> mEnvColors;
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
mpRoomDB->restoreAreaMap(ifs);
2010-08-25 00:41:43 +02:00
}
if (mVersion >= 5) {
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
ifs >> mCustomEnvColors;
2010-09-10 00:34:51 +02:00
}
if (mVersion >= 7) {
ifs >> mpRoomDB->hashToRoomID;
QMap<QString, int>::const_iterator i;
for (i = mpRoomDB->hashToRoomID.constBegin(); i != mpRoomDB->hashToRoomID.constEnd(); ++i) {
mpRoomDB->roomIDToHash.insert(i.value(), i.key());
}
2011-01-11 08:44:38 +01:00
}
Enhance: add ability to set any glyph as a room symbol (#1543) This is a squashed down commit containing several commits with messages - this is the edited combination of all the messages: As well as being able to use any grapheme it is possible to use a short word as well as anything printable from any of the Unicode Multiple Planes; although the former will become smaller to fit within both the square and round room shapes on the 2D mapper. Adds controls to the profile preference to set the (preferred) font to use to set the room symbols from and a checkbox to only use that font. Additionally a sub-dialog can be brought up which lists the details of all the different symbols on the map - showing the Unicode codepoint(s) for each and showing how they would be rendered if only the selected font is used and if any font is permitted, along with a count of the usages and the rooms that use each one... A status icon is also displayed showing whether the symbol can be rendered entirely with the selected font (green tick), only by using glyphs from other fonts (yellow ! warning) or not with the current fonts on the system (red/white cross). This allows a user to make a sensible selection of a font to use or whether they will have a problem (and a replacement by the replacement character '�') for any symbols. Updates Lua setRoomChar and getRoomChar to handle the wider range of things that can be used. getRoomChar NOW allows for an existing character to be cleared with an empty string or a space as the char attribute. The map format version has been incremented to allow the data needed to be saved directly into the binary file format but failback code is in place that means that this feature can be carried in map and room user data instead for map format versions down to 17 - the current default is 18 and there is limited support to fail gracefully down to the 16 that Mudlet 2.1 uses (all the room letter markings that are not supported will become '?', and the font data will be lost, but the correct room character data will still be in the room user data.) Following review: * I replaced some colour specifications (white and transparent) with Qt constants. * Use the same inline function flushSymbolPixmapCache() to clear the map symbol pixmap cache in all places where it might be useful. * Simplify a couple of places where an if(...) {...} else {...} can be replaced with the (...) ? (...) : (...) operator. * Limit the number of room numbers displayed for each symbol in the new widget - to avoid complications where there are huge numbers of rooms using a symbol. * Replace a use of QTableWidget::clearContents() with QTableWidgets::setRowCount(0) as I was getting some odd, deep in the Qt internal library issues {Fatal Seg. Faults!} with the former, which I suspect, but could not prove, might have been a re-entrancy issue caused by the method containing it being called indirectly by an asynchronous SIGNAL/SLOT originating in the value change from the map symbol font selection QFontComboBox... Revised to NOT do scaling when drawing room symbols from cache: the previous QPainter::drawPixmap(...) performed a scaling operation to make the symbol pixmap fit the specified rectangle. This is the cause behind the poor rendering of text characters as the scaling undoes the benefits of anti-aliasing and takes time to do. This should be faster now because the pixmaps are generated at the size/resolution they are needed (though they do have to be thrown away and regenerated if the zoom or other sizing factors change) - they do however look better to me! Also: * merged (int) TRoom::xzoom and TRoom::yzoom into TRoom::xyzoom. * added the symbol scaling "fudge-factor" to the "Special Options" tab of the "Profile preferences" dialog - it may be helpful to artificially over-size (> 1.00) or under-size (< 1.00) the symbols in some situations. * uses the word symbol rather than just glyph/grapheme in some texts. Also modified 2D mapper "Symbol" tooltip to observe that more than one letter/symbol can be used (although they will be drawn smaller so that they still fit). Add tool-tips to profile preferences dialog for font controls (except for "fudge factor" control (with range x0.50 to x2.00 for scaling of symbol to test rectangle used to fit it into the room shape)... I have consistently mispelled chosen as choosen but I have fixed that now...! Also added tooltips to map glyph usage table/widget. WorkAround: try to force a specific US mirror for zziplib on AppVeyor CI AppVeyor is based in Vancouver, Canada so the nearest SF Mirror is in the US so this commit forces the use of that mirror for that library for the CI build process as an attempt to get around the repeated, intermittent failures to get that library from SourceForge (it is now the only item that needs to be downloaded from there for such builds)... Also adds another CI file that was not mentioned before in the qmake project file and thus did not show up in the Qt IDE. Following extensive discussions it has been made clear that introducing replacements for the lua [gs]etRoomChar(...) is not going to happen. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-03-28 14:06:12 +01:00
if (mVersion >= 17) {
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
ifs >> mUserData;
Enhance: add ability to set any glyph as a room symbol (#1543) This is a squashed down commit containing several commits with messages - this is the edited combination of all the messages: As well as being able to use any grapheme it is possible to use a short word as well as anything printable from any of the Unicode Multiple Planes; although the former will become smaller to fit within both the square and round room shapes on the 2D mapper. Adds controls to the profile preference to set the (preferred) font to use to set the room symbols from and a checkbox to only use that font. Additionally a sub-dialog can be brought up which lists the details of all the different symbols on the map - showing the Unicode codepoint(s) for each and showing how they would be rendered if only the selected font is used and if any font is permitted, along with a count of the usages and the rooms that use each one... A status icon is also displayed showing whether the symbol can be rendered entirely with the selected font (green tick), only by using glyphs from other fonts (yellow ! warning) or not with the current fonts on the system (red/white cross). This allows a user to make a sensible selection of a font to use or whether they will have a problem (and a replacement by the replacement character '�') for any symbols. Updates Lua setRoomChar and getRoomChar to handle the wider range of things that can be used. getRoomChar NOW allows for an existing character to be cleared with an empty string or a space as the char attribute. The map format version has been incremented to allow the data needed to be saved directly into the binary file format but failback code is in place that means that this feature can be carried in map and room user data instead for map format versions down to 17 - the current default is 18 and there is limited support to fail gracefully down to the 16 that Mudlet 2.1 uses (all the room letter markings that are not supported will become '?', and the font data will be lost, but the correct room character data will still be in the room user data.) Following review: * I replaced some colour specifications (white and transparent) with Qt constants. * Use the same inline function flushSymbolPixmapCache() to clear the map symbol pixmap cache in all places where it might be useful. * Simplify a couple of places where an if(...) {...} else {...} can be replaced with the (...) ? (...) : (...) operator. * Limit the number of room numbers displayed for each symbol in the new widget - to avoid complications where there are huge numbers of rooms using a symbol. * Replace a use of QTableWidget::clearContents() with QTableWidgets::setRowCount(0) as I was getting some odd, deep in the Qt internal library issues {Fatal Seg. Faults!} with the former, which I suspect, but could not prove, might have been a re-entrancy issue caused by the method containing it being called indirectly by an asynchronous SIGNAL/SLOT originating in the value change from the map symbol font selection QFontComboBox... Revised to NOT do scaling when drawing room symbols from cache: the previous QPainter::drawPixmap(...) performed a scaling operation to make the symbol pixmap fit the specified rectangle. This is the cause behind the poor rendering of text characters as the scaling undoes the benefits of anti-aliasing and takes time to do. This should be faster now because the pixmaps are generated at the size/resolution they are needed (though they do have to be thrown away and regenerated if the zoom or other sizing factors change) - they do however look better to me! Also: * merged (int) TRoom::xzoom and TRoom::yzoom into TRoom::xyzoom. * added the symbol scaling "fudge-factor" to the "Special Options" tab of the "Profile preferences" dialog - it may be helpful to artificially over-size (> 1.00) or under-size (< 1.00) the symbols in some situations. * uses the word symbol rather than just glyph/grapheme in some texts. Also modified 2D mapper "Symbol" tooltip to observe that more than one letter/symbol can be used (although they will be drawn smaller so that they still fit). Add tool-tips to profile preferences dialog for font controls (except for "fudge factor" control (with range x0.50 to x2.00 for scaling of symbol to test rectangle used to fit it into the room shape)... I have consistently mispelled chosen as choosen but I have fixed that now...! Also added tooltips to map glyph usage table/widget. WorkAround: try to force a specific US mirror for zziplib on AppVeyor CI AppVeyor is based in Vancouver, Canada so the nearest SF Mirror is in the US so this commit forces the use of that mirror for that library for the CI build process as an attempt to get around the repeated, intermittent failures to get that library from SourceForge (it is now the only item that needs to be downloaded from there for such builds)... Also adds another CI file that was not mentioned before in the qmake project file and thus did not show up in the Qt IDE. Following extensive discussions it has been made clear that introducing replacements for the lua [gs]etRoomChar(...) is not going to happen. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-03-28 14:06:12 +01:00
if (mVersion >= 19) {
// Read the data from the file directly in version 19 or later
ifs >> mMapSymbolFont;
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
if ((mVersion < 21) && mMapSymbolFont.toString().split(QLatin1String(",")).size() > 15) {
// We need to clean up the effects of using QFont(string)
// for a format 17 or 18 below - as this fix went in before
// 21 was used it only has to be used for map formats 19 and
// 20:
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
mMapSymbolFont.fromString(mMapSymbolFont.toString().split(QLatin1String(",")).mid(0, 10).join(QLatin1String(",")));
}
Enhance: add ability to set any glyph as a room symbol (#1543) This is a squashed down commit containing several commits with messages - this is the edited combination of all the messages: As well as being able to use any grapheme it is possible to use a short word as well as anything printable from any of the Unicode Multiple Planes; although the former will become smaller to fit within both the square and round room shapes on the 2D mapper. Adds controls to the profile preference to set the (preferred) font to use to set the room symbols from and a checkbox to only use that font. Additionally a sub-dialog can be brought up which lists the details of all the different symbols on the map - showing the Unicode codepoint(s) for each and showing how they would be rendered if only the selected font is used and if any font is permitted, along with a count of the usages and the rooms that use each one... A status icon is also displayed showing whether the symbol can be rendered entirely with the selected font (green tick), only by using glyphs from other fonts (yellow ! warning) or not with the current fonts on the system (red/white cross). This allows a user to make a sensible selection of a font to use or whether they will have a problem (and a replacement by the replacement character '�') for any symbols. Updates Lua setRoomChar and getRoomChar to handle the wider range of things that can be used. getRoomChar NOW allows for an existing character to be cleared with an empty string or a space as the char attribute. The map format version has been incremented to allow the data needed to be saved directly into the binary file format but failback code is in place that means that this feature can be carried in map and room user data instead for map format versions down to 17 - the current default is 18 and there is limited support to fail gracefully down to the 16 that Mudlet 2.1 uses (all the room letter markings that are not supported will become '?', and the font data will be lost, but the correct room character data will still be in the room user data.) Following review: * I replaced some colour specifications (white and transparent) with Qt constants. * Use the same inline function flushSymbolPixmapCache() to clear the map symbol pixmap cache in all places where it might be useful. * Simplify a couple of places where an if(...) {...} else {...} can be replaced with the (...) ? (...) : (...) operator. * Limit the number of room numbers displayed for each symbol in the new widget - to avoid complications where there are huge numbers of rooms using a symbol. * Replace a use of QTableWidget::clearContents() with QTableWidgets::setRowCount(0) as I was getting some odd, deep in the Qt internal library issues {Fatal Seg. Faults!} with the former, which I suspect, but could not prove, might have been a re-entrancy issue caused by the method containing it being called indirectly by an asynchronous SIGNAL/SLOT originating in the value change from the map symbol font selection QFontComboBox... Revised to NOT do scaling when drawing room symbols from cache: the previous QPainter::drawPixmap(...) performed a scaling operation to make the symbol pixmap fit the specified rectangle. This is the cause behind the poor rendering of text characters as the scaling undoes the benefits of anti-aliasing and takes time to do. This should be faster now because the pixmaps are generated at the size/resolution they are needed (though they do have to be thrown away and regenerated if the zoom or other sizing factors change) - they do however look better to me! Also: * merged (int) TRoom::xzoom and TRoom::yzoom into TRoom::xyzoom. * added the symbol scaling "fudge-factor" to the "Special Options" tab of the "Profile preferences" dialog - it may be helpful to artificially over-size (> 1.00) or under-size (< 1.00) the symbols in some situations. * uses the word symbol rather than just glyph/grapheme in some texts. Also modified 2D mapper "Symbol" tooltip to observe that more than one letter/symbol can be used (although they will be drawn smaller so that they still fit). Add tool-tips to profile preferences dialog for font controls (except for "fudge factor" control (with range x0.50 to x2.00 for scaling of symbol to test rectangle used to fit it into the room shape)... I have consistently mispelled chosen as choosen but I have fixed that now...! Also added tooltips to map glyph usage table/widget. WorkAround: try to force a specific US mirror for zziplib on AppVeyor CI AppVeyor is based in Vancouver, Canada so the nearest SF Mirror is in the US so this commit forces the use of that mirror for that library for the CI build process as an attempt to get around the repeated, intermittent failures to get that library from SourceForge (it is now the only item that needs to be downloaded from there for such builds)... Also adds another CI file that was not mentioned before in the qmake project file and thus did not show up in the Qt IDE. Following extensive discussions it has been made clear that introducing replacements for the lua [gs]etRoomChar(...) is not going to happen. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-03-28 14:06:12 +01:00
ifs >> mMapSymbolFontFudgeFactor;
ifs >> mIsOnlyMapSymbolFontToBeUsed;
// Clean up stale fallback keys that past versions could leave
// behind in the live map's user data (and thus in files saved
// from it) after saving in a format before 19:
mUserData.remove(qsl("system.fallback_mapSymbolFont"));
mUserData.remove(qsl("system.fallback_mapSymbolFontFudgeFactor"));
mUserData.remove(qsl("system.fallback_onlyUseMapSymbolFont"));
Enhance: add ability to set any glyph as a room symbol (#1543) This is a squashed down commit containing several commits with messages - this is the edited combination of all the messages: As well as being able to use any grapheme it is possible to use a short word as well as anything printable from any of the Unicode Multiple Planes; although the former will become smaller to fit within both the square and round room shapes on the 2D mapper. Adds controls to the profile preference to set the (preferred) font to use to set the room symbols from and a checkbox to only use that font. Additionally a sub-dialog can be brought up which lists the details of all the different symbols on the map - showing the Unicode codepoint(s) for each and showing how they would be rendered if only the selected font is used and if any font is permitted, along with a count of the usages and the rooms that use each one... A status icon is also displayed showing whether the symbol can be rendered entirely with the selected font (green tick), only by using glyphs from other fonts (yellow ! warning) or not with the current fonts on the system (red/white cross). This allows a user to make a sensible selection of a font to use or whether they will have a problem (and a replacement by the replacement character '�') for any symbols. Updates Lua setRoomChar and getRoomChar to handle the wider range of things that can be used. getRoomChar NOW allows for an existing character to be cleared with an empty string or a space as the char attribute. The map format version has been incremented to allow the data needed to be saved directly into the binary file format but failback code is in place that means that this feature can be carried in map and room user data instead for map format versions down to 17 - the current default is 18 and there is limited support to fail gracefully down to the 16 that Mudlet 2.1 uses (all the room letter markings that are not supported will become '?', and the font data will be lost, but the correct room character data will still be in the room user data.) Following review: * I replaced some colour specifications (white and transparent) with Qt constants. * Use the same inline function flushSymbolPixmapCache() to clear the map symbol pixmap cache in all places where it might be useful. * Simplify a couple of places where an if(...) {...} else {...} can be replaced with the (...) ? (...) : (...) operator. * Limit the number of room numbers displayed for each symbol in the new widget - to avoid complications where there are huge numbers of rooms using a symbol. * Replace a use of QTableWidget::clearContents() with QTableWidgets::setRowCount(0) as I was getting some odd, deep in the Qt internal library issues {Fatal Seg. Faults!} with the former, which I suspect, but could not prove, might have been a re-entrancy issue caused by the method containing it being called indirectly by an asynchronous SIGNAL/SLOT originating in the value change from the map symbol font selection QFontComboBox... Revised to NOT do scaling when drawing room symbols from cache: the previous QPainter::drawPixmap(...) performed a scaling operation to make the symbol pixmap fit the specified rectangle. This is the cause behind the poor rendering of text characters as the scaling undoes the benefits of anti-aliasing and takes time to do. This should be faster now because the pixmaps are generated at the size/resolution they are needed (though they do have to be thrown away and regenerated if the zoom or other sizing factors change) - they do however look better to me! Also: * merged (int) TRoom::xzoom and TRoom::yzoom into TRoom::xyzoom. * added the symbol scaling "fudge-factor" to the "Special Options" tab of the "Profile preferences" dialog - it may be helpful to artificially over-size (> 1.00) or under-size (< 1.00) the symbols in some situations. * uses the word symbol rather than just glyph/grapheme in some texts. Also modified 2D mapper "Symbol" tooltip to observe that more than one letter/symbol can be used (although they will be drawn smaller so that they still fit). Add tool-tips to profile preferences dialog for font controls (except for "fudge factor" control (with range x0.50 to x2.00 for scaling of symbol to test rectangle used to fit it into the room shape)... I have consistently mispelled chosen as choosen but I have fixed that now...! Also added tooltips to map glyph usage table/widget. WorkAround: try to force a specific US mirror for zziplib on AppVeyor CI AppVeyor is based in Vancouver, Canada so the nearest SF Mirror is in the US so this commit forces the use of that mirror for that library for the CI build process as an attempt to get around the repeated, intermittent failures to get that library from SourceForge (it is now the only item that needs to be downloaded from there for such builds)... Also adds another CI file that was not mentioned before in the qmake project file and thus did not show up in the Qt IDE. Following extensive discussions it has been made clear that introducing replacements for the lua [gs]etRoomChar(...) is not going to happen. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-03-28 14:06:12 +01:00
} else {
// Fallback to reading the data from the map user data - and
// remove it from the data the user will see:
// BUGFIX: Using QFont::toString() and then using that to
// construct a font again afterwards via a QFont(string) was
// incorrect as it seemed to cause the last to duplicated the
// last nine elements each time. The details of the ::toString()
// ::fromString() methods are not currently documented so the
// only details are documented in the source:
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/gui/text/qfont.cpp?h=5.15#n2070
// and:
// https://code.qt.io/cgit/qt/qtbase.git/tree/src/gui/text/qfont.cpp?h=5.15#n2128
// this suggests that only one or ten elements are accepted so
// we CAN fix past mistakes by only considering the first ten
// elements:
const QStringList fontStrings{mUserData.take(qsl("system.fallback_mapSymbolFont")).split(QLatin1Char(','))};
const QString fontString{fontStrings.mid(0, 10).join(QLatin1Char(','))};
const QString fontFudgeFactorString = mUserData.take(qsl("system.fallback_mapSymbolFontFudgeFactor"));
const QString onlyUseSymbolFontString = mUserData.take(qsl("system.fallback_onlyUseMapSymbolFont"));
Enhance: add ability to set any glyph as a room symbol (#1543) This is a squashed down commit containing several commits with messages - this is the edited combination of all the messages: As well as being able to use any grapheme it is possible to use a short word as well as anything printable from any of the Unicode Multiple Planes; although the former will become smaller to fit within both the square and round room shapes on the 2D mapper. Adds controls to the profile preference to set the (preferred) font to use to set the room symbols from and a checkbox to only use that font. Additionally a sub-dialog can be brought up which lists the details of all the different symbols on the map - showing the Unicode codepoint(s) for each and showing how they would be rendered if only the selected font is used and if any font is permitted, along with a count of the usages and the rooms that use each one... A status icon is also displayed showing whether the symbol can be rendered entirely with the selected font (green tick), only by using glyphs from other fonts (yellow ! warning) or not with the current fonts on the system (red/white cross). This allows a user to make a sensible selection of a font to use or whether they will have a problem (and a replacement by the replacement character '�') for any symbols. Updates Lua setRoomChar and getRoomChar to handle the wider range of things that can be used. getRoomChar NOW allows for an existing character to be cleared with an empty string or a space as the char attribute. The map format version has been incremented to allow the data needed to be saved directly into the binary file format but failback code is in place that means that this feature can be carried in map and room user data instead for map format versions down to 17 - the current default is 18 and there is limited support to fail gracefully down to the 16 that Mudlet 2.1 uses (all the room letter markings that are not supported will become '?', and the font data will be lost, but the correct room character data will still be in the room user data.) Following review: * I replaced some colour specifications (white and transparent) with Qt constants. * Use the same inline function flushSymbolPixmapCache() to clear the map symbol pixmap cache in all places where it might be useful. * Simplify a couple of places where an if(...) {...} else {...} can be replaced with the (...) ? (...) : (...) operator. * Limit the number of room numbers displayed for each symbol in the new widget - to avoid complications where there are huge numbers of rooms using a symbol. * Replace a use of QTableWidget::clearContents() with QTableWidgets::setRowCount(0) as I was getting some odd, deep in the Qt internal library issues {Fatal Seg. Faults!} with the former, which I suspect, but could not prove, might have been a re-entrancy issue caused by the method containing it being called indirectly by an asynchronous SIGNAL/SLOT originating in the value change from the map symbol font selection QFontComboBox... Revised to NOT do scaling when drawing room symbols from cache: the previous QPainter::drawPixmap(...) performed a scaling operation to make the symbol pixmap fit the specified rectangle. This is the cause behind the poor rendering of text characters as the scaling undoes the benefits of anti-aliasing and takes time to do. This should be faster now because the pixmaps are generated at the size/resolution they are needed (though they do have to be thrown away and regenerated if the zoom or other sizing factors change) - they do however look better to me! Also: * merged (int) TRoom::xzoom and TRoom::yzoom into TRoom::xyzoom. * added the symbol scaling "fudge-factor" to the "Special Options" tab of the "Profile preferences" dialog - it may be helpful to artificially over-size (> 1.00) or under-size (< 1.00) the symbols in some situations. * uses the word symbol rather than just glyph/grapheme in some texts. Also modified 2D mapper "Symbol" tooltip to observe that more than one letter/symbol can be used (although they will be drawn smaller so that they still fit). Add tool-tips to profile preferences dialog for font controls (except for "fudge factor" control (with range x0.50 to x2.00 for scaling of symbol to test rectangle used to fit it into the room shape)... I have consistently mispelled chosen as choosen but I have fixed that now...! Also added tooltips to map glyph usage table/widget. WorkAround: try to force a specific US mirror for zziplib on AppVeyor CI AppVeyor is based in Vancouver, Canada so the nearest SF Mirror is in the US so this commit forces the use of that mirror for that library for the CI build process as an attempt to get around the repeated, intermittent failures to get that library from SourceForge (it is now the only item that needs to be downloaded from there for such builds)... Also adds another CI file that was not mentioned before in the qmake project file and thus did not show up in the Qt IDE. Following extensive discussions it has been made clear that introducing replacements for the lua [gs]etRoomChar(...) is not going to happen. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-03-28 14:06:12 +01:00
if (!fontString.isEmpty()) {
mMapSymbolFont.fromString(fontString);
Enhance: add ability to set any glyph as a room symbol (#1543) This is a squashed down commit containing several commits with messages - this is the edited combination of all the messages: As well as being able to use any grapheme it is possible to use a short word as well as anything printable from any of the Unicode Multiple Planes; although the former will become smaller to fit within both the square and round room shapes on the 2D mapper. Adds controls to the profile preference to set the (preferred) font to use to set the room symbols from and a checkbox to only use that font. Additionally a sub-dialog can be brought up which lists the details of all the different symbols on the map - showing the Unicode codepoint(s) for each and showing how they would be rendered if only the selected font is used and if any font is permitted, along with a count of the usages and the rooms that use each one... A status icon is also displayed showing whether the symbol can be rendered entirely with the selected font (green tick), only by using glyphs from other fonts (yellow ! warning) or not with the current fonts on the system (red/white cross). This allows a user to make a sensible selection of a font to use or whether they will have a problem (and a replacement by the replacement character '�') for any symbols. Updates Lua setRoomChar and getRoomChar to handle the wider range of things that can be used. getRoomChar NOW allows for an existing character to be cleared with an empty string or a space as the char attribute. The map format version has been incremented to allow the data needed to be saved directly into the binary file format but failback code is in place that means that this feature can be carried in map and room user data instead for map format versions down to 17 - the current default is 18 and there is limited support to fail gracefully down to the 16 that Mudlet 2.1 uses (all the room letter markings that are not supported will become '?', and the font data will be lost, but the correct room character data will still be in the room user data.) Following review: * I replaced some colour specifications (white and transparent) with Qt constants. * Use the same inline function flushSymbolPixmapCache() to clear the map symbol pixmap cache in all places where it might be useful. * Simplify a couple of places where an if(...) {...} else {...} can be replaced with the (...) ? (...) : (...) operator. * Limit the number of room numbers displayed for each symbol in the new widget - to avoid complications where there are huge numbers of rooms using a symbol. * Replace a use of QTableWidget::clearContents() with QTableWidgets::setRowCount(0) as I was getting some odd, deep in the Qt internal library issues {Fatal Seg. Faults!} with the former, which I suspect, but could not prove, might have been a re-entrancy issue caused by the method containing it being called indirectly by an asynchronous SIGNAL/SLOT originating in the value change from the map symbol font selection QFontComboBox... Revised to NOT do scaling when drawing room symbols from cache: the previous QPainter::drawPixmap(...) performed a scaling operation to make the symbol pixmap fit the specified rectangle. This is the cause behind the poor rendering of text characters as the scaling undoes the benefits of anti-aliasing and takes time to do. This should be faster now because the pixmaps are generated at the size/resolution they are needed (though they do have to be thrown away and regenerated if the zoom or other sizing factors change) - they do however look better to me! Also: * merged (int) TRoom::xzoom and TRoom::yzoom into TRoom::xyzoom. * added the symbol scaling "fudge-factor" to the "Special Options" tab of the "Profile preferences" dialog - it may be helpful to artificially over-size (> 1.00) or under-size (< 1.00) the symbols in some situations. * uses the word symbol rather than just glyph/grapheme in some texts. Also modified 2D mapper "Symbol" tooltip to observe that more than one letter/symbol can be used (although they will be drawn smaller so that they still fit). Add tool-tips to profile preferences dialog for font controls (except for "fudge factor" control (with range x0.50 to x2.00 for scaling of symbol to test rectangle used to fit it into the room shape)... I have consistently mispelled chosen as choosen but I have fixed that now...! Also added tooltips to map glyph usage table/widget. WorkAround: try to force a specific US mirror for zziplib on AppVeyor CI AppVeyor is based in Vancouver, Canada so the nearest SF Mirror is in the US so this commit forces the use of that mirror for that library for the CI build process as an attempt to get around the repeated, intermittent failures to get that library from SourceForge (it is now the only item that needs to be downloaded from there for such builds)... Also adds another CI file that was not mentioned before in the qmake project file and thus did not show up in the Qt IDE. Following extensive discussions it has been made clear that introducing replacements for the lua [gs]etRoomChar(...) is not going to happen. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-03-28 14:06:12 +01:00
}
if (!fontFudgeFactorString.isEmpty()) {
mMapSymbolFontFudgeFactor = fontFudgeFactorString.toDouble();
}
if (!onlyUseSymbolFontString.isEmpty()) {
mIsOnlyMapSymbolFontToBeUsed = (onlyUseSymbolFontString != QLatin1String("false"));
}
}
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
}
Enhance: add ability to set any glyph as a room symbol (#1543) This is a squashed down commit containing several commits with messages - this is the edited combination of all the messages: As well as being able to use any grapheme it is possible to use a short word as well as anything printable from any of the Unicode Multiple Planes; although the former will become smaller to fit within both the square and round room shapes on the 2D mapper. Adds controls to the profile preference to set the (preferred) font to use to set the room symbols from and a checkbox to only use that font. Additionally a sub-dialog can be brought up which lists the details of all the different symbols on the map - showing the Unicode codepoint(s) for each and showing how they would be rendered if only the selected font is used and if any font is permitted, along with a count of the usages and the rooms that use each one... A status icon is also displayed showing whether the symbol can be rendered entirely with the selected font (green tick), only by using glyphs from other fonts (yellow ! warning) or not with the current fonts on the system (red/white cross). This allows a user to make a sensible selection of a font to use or whether they will have a problem (and a replacement by the replacement character '�') for any symbols. Updates Lua setRoomChar and getRoomChar to handle the wider range of things that can be used. getRoomChar NOW allows for an existing character to be cleared with an empty string or a space as the char attribute. The map format version has been incremented to allow the data needed to be saved directly into the binary file format but failback code is in place that means that this feature can be carried in map and room user data instead for map format versions down to 17 - the current default is 18 and there is limited support to fail gracefully down to the 16 that Mudlet 2.1 uses (all the room letter markings that are not supported will become '?', and the font data will be lost, but the correct room character data will still be in the room user data.) Following review: * I replaced some colour specifications (white and transparent) with Qt constants. * Use the same inline function flushSymbolPixmapCache() to clear the map symbol pixmap cache in all places where it might be useful. * Simplify a couple of places where an if(...) {...} else {...} can be replaced with the (...) ? (...) : (...) operator. * Limit the number of room numbers displayed for each symbol in the new widget - to avoid complications where there are huge numbers of rooms using a symbol. * Replace a use of QTableWidget::clearContents() with QTableWidgets::setRowCount(0) as I was getting some odd, deep in the Qt internal library issues {Fatal Seg. Faults!} with the former, which I suspect, but could not prove, might have been a re-entrancy issue caused by the method containing it being called indirectly by an asynchronous SIGNAL/SLOT originating in the value change from the map symbol font selection QFontComboBox... Revised to NOT do scaling when drawing room symbols from cache: the previous QPainter::drawPixmap(...) performed a scaling operation to make the symbol pixmap fit the specified rectangle. This is the cause behind the poor rendering of text characters as the scaling undoes the benefits of anti-aliasing and takes time to do. This should be faster now because the pixmaps are generated at the size/resolution they are needed (though they do have to be thrown away and regenerated if the zoom or other sizing factors change) - they do however look better to me! Also: * merged (int) TRoom::xzoom and TRoom::yzoom into TRoom::xyzoom. * added the symbol scaling "fudge-factor" to the "Special Options" tab of the "Profile preferences" dialog - it may be helpful to artificially over-size (> 1.00) or under-size (< 1.00) the symbols in some situations. * uses the word symbol rather than just glyph/grapheme in some texts. Also modified 2D mapper "Symbol" tooltip to observe that more than one letter/symbol can be used (although they will be drawn smaller so that they still fit). Add tool-tips to profile preferences dialog for font controls (except for "fudge factor" control (with range x0.50 to x2.00 for scaling of symbol to test rectangle used to fit it into the room shape)... I have consistently mispelled chosen as choosen but I have fixed that now...! Also added tooltips to map glyph usage table/widget. WorkAround: try to force a specific US mirror for zziplib on AppVeyor CI AppVeyor is based in Vancouver, Canada so the nearest SF Mirror is in the US so this commit forces the use of that mirror for that library for the CI build process as an attempt to get around the repeated, intermittent failures to get that library from SourceForge (it is now the only item that needs to be downloaded from there for such builds)... Also adds another CI file that was not mentioned before in the qmake project file and thus did not show up in the Qt IDE. Following extensive discussions it has been made clear that introducing replacements for the lua [gs]etRoomChar(...) is not going to happen. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-03-28 14:06:12 +01:00
mMapSymbolFont.setStyleStrategy(static_cast<QFont::StyleStrategy>((mIsOnlyMapSymbolFontToBeUsed ? QFont::NoFontMerging : 0) | QFont::PreferOutline | QFont::PreferAntialias
| QFont::PreferQuality | QFont::PreferNoShaping));
if (mVersion >= 14) {
2021-04-02 19:10:16 +01:00
int areaSize = 0;
ifs >> areaSize;
// restore area table
for (int i = 0; i < areaSize; i++) {
improve: improve memory safety by using smart pointers (#9239) ### Refactor: replace raw pointer ownership with smart pointers across core subsystems #### Brief overview of PR changes/additions Replaces raw pointer ownership patterns with `std::unique_ptr` and `std::map` across several core subsystems: - **Host**: `mStopWatchMap` (`QMap<int, stopWatch*>` → `std::map<int, unique_ptr<stopWatch>>`), `profileShortcuts` (`QMap<QString, QKeySequence*>` → `std::map<QString, unique_ptr<QKeySequence>>`). Removes `qDeleteAll` in destructor and `delete mMMCPServer`. - **TMap**: `mpRoomDB` raw pointer → `unique_ptr` - **VarUnit**: `base` raw pointer → `unique_ptr` - **TTrigger**: condition map storage converted to `unique_ptr`, destructor simplified - **discord**: handler and presence maps converted from raw pointer `QMap` to `unique_ptr` + `std::map` - **Updater**: `mFeed` and `mUpdateDialog` converted to `unique_ptr` #### Motivation for adding to Mudlet These patterns were identified as sources of memory leaks and potential use-after-free bugs. Using smart pointers makes ownership explicit, eliminates manual cleanup code, and ensures correct destruction even on early-exit paths. #### Other info (issues closed, discussion etc) sorry this one is still pretty big, but most of the changes are the same for each thing so reviewing them together probably makes sense. sadly there isn't much to see here other than no slow uptick of heap size :-[ Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:42:09 +12:00
auto pA = new TArea(this, mpRoomDB.get());
2021-04-02 19:10:16 +01:00
int areaID = 0;
ifs >> areaID;
if (mVersion >= 18) {
// In version 18 changed from QList<int> to QSet<int> as the later is
// faster in many of the cases where we use it.
ifs >> pA->rooms;
} else {
QList<int> oldRoomsList;
ifs >> oldRoomsList;
pA->rooms = QSet<int>{oldRoomsList.begin(), oldRoomsList.end()};
enhanceAndFix: fix handling of parallel edges in BGL route-finding graph This commit cleans up some problems in route finding - specifically when working out the exits to use to move from the ordered list of rooms that make up the route that the A* code determined - no longer is the first exit in a fixed order in a particular room used that happens to go to the next room - instead the correct (lowest weighted, non-locked) exit is selected. If a route is not found the reason why is output via qDebug() which should make debugging problems a bit easier for developers! The BGL graph that TMap::initgraph() producess now tracks which exit from one room to another is the best one to use (choosing just one from equally weighted ones and ignores higher weighted ones) if it is a "normal" exit the subsequent use of TMap:findPath() will now insert a "translated" direction to the TMap::mDirList - but in future it should be straightforward to arrange for a user specified "direction" name to be used - perhaps with locale specific defaults which will make using Mudlet's route-finding code possible with non-ASCII using MUDs (i.e. those not based on American English!) This commit also avoids creating spurious entries in the BGL graph that the previous code did by using the "[]" operator (which inserted *wrong* entries into (QMap<int, int>) TMap::roomidToIndex for TRooms that should NOT have been present!) That was found to be causing crashes in corner cases where ALL rooms in the map or at least some rooms or their exits in what would otherwise have been a valid route were locked against use for route-finding. Also: * Culls some dead code in TAstar.h that was copied verbatim from a usage example elsewhere (possible the boost library documentation). * Removes following unused members of TMap: * (QList<int>) mTestedNodes * (QList<int>) conList * (int) mPlausaOptOut; * typedef of: mygraph_t::vertex_iterator to: vertex_iterator * typedef of: std::pair<int, int> to: edge * Comments out the now unused members of TMap: * (QMap<int, int>) indexToRoomid * Corrects spelling of TAstar.h in qmake project file - was spelt TAStar.h! * Generates a "speedWalkWeight" table alongside the "speedWalkPath" and "speedWalkDir" ones that indicates the weight of each step in a route, it can be accessed in the same manner as those others. * Host::assemblePath() now returns the total "weight" of the route calculated - which the lua command getPath(startRoomId, targetRoomId) now returns as a second value - this will make it easier for users' scripts to choose between routes to multiple destinations. * Some Lua helper methods: * TLuaInterpreter::get_lua_string(...) * TLuaInterpreter::set_lua_string(...) * TLuaInterpreter::set_lua_table(...) now process strings as Utf-8 - this change was needed to allow non-ASCII characters to appear in exit directions but will also be needed by other commands. Whilst the first is currently unused, the second is used once in three class and the third by Host::assemblePath() and twice in TLuaInterpreter::initLuaGlobals() to set up something for "atcp" and "channel102" processing... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2015-07-19 20:38:13 +01:00
}
// Can be useful when analysing suspect map files!
// qDebug() << "TMap::restore(...)" << "Area:" << areaID;
// qDebug() << "Rooms:" << pA->rooms;
ifs >> pA->zLevels;
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
ifs >> pA->mAreaExits;
ifs >> pA->gridMode;
ifs >> pA->max_x;
ifs >> pA->max_y;
ifs >> pA->max_z;
ifs >> pA->min_x;
ifs >> pA->min_y;
ifs >> pA->min_z;
ifs >> pA->span;
if (mVersion >= 17) {
ifs >> pA->xmaxForZ;
ifs >> pA->ymaxForZ;
ifs >> pA->xminForZ;
ifs >> pA->yminForZ;
} else {
QMap<int, int> dummyMinMaxForZ;
ifs >> pA->xmaxForZ;
ifs >> pA->ymaxForZ;
ifs >> dummyMinMaxForZ;
ifs >> pA->xminForZ;
ifs >> pA->yminForZ;
ifs >> dummyMinMaxForZ;
Enhance: 2D Map Room Selection, better big map performance + other mods In situations when we check whether a room in an area both for internal purposes and when rooms on a mapper is selected, using QSet instead of a QList is faster in performance for large numbers of entries in set. As it reworks the mapper code it also fixes issue where the multi-room selection widget overwrites map info display - the latter is re-sized and re-positioned (and regains a semi-transparent background which helped to show this working during debugging!) The former is now: dynamically resized to only take up enough vertical space to show the selected rooms; also displays the associate room names if there are any, expanding the widget as required; sorts the display either by room name or number and in either direction. The mouse wheel handler is modified so that using the scroll wheel ONLY scrolls the list within the widget - previously (by default) once the end in either direction was hit the related events would be passed up the widget chain where it would otherwise invoke the 2D mapper's zoom in/out code. In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x) QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method, using only the Y-component the latter provides. If the Control modifier is active the zoom value is modified by an extra x10 factor which is useful when working with large maps as otherwise the zooming rate is "slow" at high values - ideally the control should be logarithmic or exponential or some other "non-linear" algorithm to work more uniformly over the range of practical use cases. The code to paint the map info text has been revised also to use the mMapInfoRect which was being defined but NOT used. The info text now reports whether the room name is for the player room {set via the Lua command centerview(roomId)} or is one that is selected by mouse dragging - and if more than one room is selected by that indicates the count of rooms in the selection. In the case of multiple rooms being selected the room that single room context menu operations will act upon is highlighted by the same style of yellow target used to show the custom exit line destination but is drawn in a different point in the code so that it is drawn over the rooms. Because of the change to the way that multiple rooms are selected routines that use that information had to be revised - in doing so it was possible to improve the usability/operation of: T2DMap::slot_movePosition() T2DMap::slot_setCharacter() T2DMap::slot_spread() T2DMap::slot_shrink() T2DMap::slot_lockRoom(): T2DMap::slot_unlockRoom(): This method, also resurrected here to the 2D mapper context menu, as it is also affected by the changes: T2DMap::slot_setPlayerLocation() There was a slot_setPlayerLocation code that set a global lua variable mRoomSet and moved the player to that room Id (introduced in commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D Mapper context menu item that called it was commented out and thus removed from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without any explaination. Since that has not been used since then I have replaced it with a new Event: sysManualLocationSetEvent with a single numeric value which is the new (valid) room Id number - user scripts can capture this event if they want to know that the user has manually re-positioned the current player room in the 2D mapper. In passing: * Fixed Text font changing between docked and un-docked forms of the built-in map widget (when not incorporated into a console) - as it was not previously explicitly set it assumed the Application one whilst docked but the Qt System one when a free floating widget - and the two do not have to be the same. This fixes: https://bugs.launchpad.net/mudlet/+bug/1432841 . * Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in T2DMap::wheelEvent(...); will need duplicating in TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) . * Adds the profile name to the Mapper dockable widget so that it's parentage can be determined when multiple profiles are active. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-03-08 08:35:07 +00:00
}
ifs >> pA->pos;
ifs >> pA->isZone;
ifs >> pA->zoneAreaRef;
Improve: remember 2D mapper zoom amounts between sessions (#6615) This is intended to close #2388. This enables the 2D (only) map zoom amounts for each map area to be save independently and restored when switching between areas in the mapper. It also saves the data between session. It extends the existing `setMapZoom(...)` API to take an optional second argument to specify the map area ID to set the zoom (which is a floating point number) for any existing area, not just the current one. It also adds a `getMapZoom(...)` function that, without any arguments, returns the currently used 2D map zoom value for the area currently being shown in the 2D mapper. If an area ID is provided it instead returns the value that was last used for that area - or the default value that is used initially on starting the profile or for an area that has not been viewed before. Importantly when switching between the areas in the 2D mapper the values are retained and applied so that one area can be zoomed in and another zoomed out and switching from the first to the second and back to the first means that the zoom level used in the first is reused when it is returned to. Deleting an area will forget the stored zoom level so if it is reused it starts from scratch. Code to save the zoom level for each area has also been implemented within the C++ core. It saves it in the Area User Data for current map formats (but removes it on loading so the user never sees it there) under a `system.fallback_map2DZoom` key but will save it directly in the binary data (which is more efficient) in the next format version whenever it is enabled. A new Mudlet event, which has been called `sysMapAreaChanged` has been added with two additional arguments being the area ID changed to followed by the one that it was changed from. I originally thought I would need it to handle saving the zoom level for each area via the Lua system but I found that that was not practicable. Also, in refactoring `T2DMap::paintEvent(...)` I: Removed/combined some locals: * `(TArea*) playerArea` and `pPlayerArea` and `pArea`==> `pDrawnArea` * `(TRoom*) playerRoom` ==> `pPlayerRoom` Remove unneeded (refactored out): * `(qreal) ox` * `(qreal) oy` Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2023-03-16 15:00:33 +00:00
if (mVersion >= 21) {
ifs >> pA->mLast2DMapZoom;
ifs >> pA->mUserData;
} else if (mVersion >= 17) {
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
ifs >> pA->mUserData;
const qreal fallback_map2DZoom = pA->mUserData.take(QLatin1String("system.fallback_map2DZoom")).toDouble();
Improve: remember 2D mapper zoom amounts between sessions (#6615) This is intended to close #2388. This enables the 2D (only) map zoom amounts for each map area to be save independently and restored when switching between areas in the mapper. It also saves the data between session. It extends the existing `setMapZoom(...)` API to take an optional second argument to specify the map area ID to set the zoom (which is a floating point number) for any existing area, not just the current one. It also adds a `getMapZoom(...)` function that, without any arguments, returns the currently used 2D map zoom value for the area currently being shown in the 2D mapper. If an area ID is provided it instead returns the value that was last used for that area - or the default value that is used initially on starting the profile or for an area that has not been viewed before. Importantly when switching between the areas in the 2D mapper the values are retained and applied so that one area can be zoomed in and another zoomed out and switching from the first to the second and back to the first means that the zoom level used in the first is reused when it is returned to. Deleting an area will forget the stored zoom level so if it is reused it starts from scratch. Code to save the zoom level for each area has also been implemented within the C++ core. It saves it in the Area User Data for current map formats (but removes it on loading so the user never sees it there) under a `system.fallback_map2DZoom` key but will save it directly in the binary data (which is more efficient) in the next format version whenever it is enabled. A new Mudlet event, which has been called `sysMapAreaChanged` has been added with two additional arguments being the area ID changed to followed by the one that it was changed from. I originally thought I would need it to handle saving the zoom level for each area via the Lua system but I found that that was not practicable. Also, in refactoring `T2DMap::paintEvent(...)` I: Removed/combined some locals: * `(TArea*) playerArea` and `pPlayerArea` and `pArea`==> `pDrawnArea` * `(TRoom*) playerRoom` ==> `pPlayerRoom` Remove unneeded (refactored out): * `(qreal) ox` * `(qreal) oy` Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2023-03-16 15:00:33 +00:00
pA->mLast2DMapZoom = (fallback_map2DZoom >= T2DMap::csmMinXYZoom) ? fallback_map2DZoom : T2DMap::csmDefaultXYZoom;
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
}
if (mVersion >= 21) {
int mapLabelsCount = -1;
ifs >> mapLabelsCount;
for (int i = 0; i < mapLabelsCount; ++i) {
int labelId = -1;
ifs >> labelId;
TMapLabel label;
Add per-room border color and thickness (#8758) #### Brief overview of PR changes/additions Adds per-room border color and thickness settings for the 2D mapper. Rooms can now have custom borders to visually distinguish them (e.g., indoor vs outdoor). New Lua functions: - `setRoomBorderColor(roomID, r, g, b[, a])` / `getRoomBorderColor()` / `clearRoomBorderColor()` - `setRoomBorderThickness(roomID, thickness)` / `getRoomBorderThickness()` / `clearRoomBorderThickness()` UI controls added to the room properties dialog. #### Motivation for adding to Mudlet [User request](https://discord.com/channels/283581582550237184/792073945922142259/1457314371184365569) to visually distinguish room types on maps, previously only possible in CMUD. #### Other info (issues closed, discussion etc) **Test case:** 1. Open a map with rooms 2. Run: `setRoomBorderColor(1, 255, 0, 0)` and `setRoomBorderThickness(1, 3)` 3. Room 1 should display with a thick red border 4. Run: `clearRoomBorderColor(1)` - border returns to global default color 5. Right-click a room → Properties → Border section allows setting color/thickness via UI https://github.com/user-attachments/assets/1261b84f-0ba1-4719-9f56-1870ba51e4d1 I looked into bumping the map format to 21 and storing the data natively, not using userdata - but then my map grew from 7.9MB to 8.7MB without me having changed any room's data at all! Just the extra structures, now empty, per room, added this might weight. In the end, going with a "sparse" storage solution of using room userdata is more space-efficient and less of an issue for backwards compatibility. --------- Co-authored-by: Vadim Peretokin <vadi2@users.noreply.github.com>
2026-01-12 19:16:27 +01:00
ifs >> label.pos;
ifs >> label.size;
ifs >> label.text;
ifs >> label.fgColor;
ifs >> label.bgColor;
ifs >> label.pix;
ifs >> label.noScaling;
ifs >> label.showOnTop;
restoreLabelFontFromUserData(label, labelId, pA->mUserData);
restoreLabelOutlineColorFromUserData(label, labelId, pA->mUserData);
pA->mMapLabels.insert(labelId, label);
}
}
mpRoomDB->restoreSingleArea(areaID, pA);
}
}
if (!mpRoomDB->getAreaMap().keys().contains(-1)) {
improve: improve memory safety by using smart pointers (#9239) ### Refactor: replace raw pointer ownership with smart pointers across core subsystems #### Brief overview of PR changes/additions Replaces raw pointer ownership patterns with `std::unique_ptr` and `std::map` across several core subsystems: - **Host**: `mStopWatchMap` (`QMap<int, stopWatch*>` → `std::map<int, unique_ptr<stopWatch>>`), `profileShortcuts` (`QMap<QString, QKeySequence*>` → `std::map<QString, unique_ptr<QKeySequence>>`). Removes `qDeleteAll` in destructor and `delete mMMCPServer`. - **TMap**: `mpRoomDB` raw pointer → `unique_ptr` - **VarUnit**: `base` raw pointer → `unique_ptr` - **TTrigger**: condition map storage converted to `unique_ptr`, destructor simplified - **discord**: handler and presence maps converted from raw pointer `QMap` to `unique_ptr` + `std::map` - **Updater**: `mFeed` and `mUpdateDialog` converted to `unique_ptr` #### Motivation for adding to Mudlet These patterns were identified as sources of memory leaks and potential use-after-free bugs. Using smart pointers makes ownership explicit, eliminates manual cleanup code, and ensures correct destruction even on early-exit paths. #### Other info (issues closed, discussion etc) sorry this one is still pretty big, but most of the changes are the same for each thing so reviewing them together probably makes sense. sadly there isn't much to see here other than no slow uptick of heap size :-[ Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:42:09 +12:00
auto pDefaultA = new TArea(this, mpRoomDB.get());
mpRoomDB->restoreSingleArea(-1, pDefaultA);
const QString defaultAreaInsertionMsg = tr("[ INFO ] - Default (reset) area (for rooms that have not been assigned to an\n"
"area) not found, adding reserved -1 id.");
appendErrorMsgWithNoLf(defaultAreaInsertionMsg, false);
if (mudlet::self()->showMapAuditErrors()) {
postMessage(defaultAreaInsertionMsg);
}
}
if (mVersion >= 18) {
// In version 18 we changed to store the "userRoom" for each profile
// so that when copied/shared between profiles they do not interfere
// with each other's saved value
ifs >> mRoomIdHash;
} else if (mVersion >= 12) {
2021-04-02 19:10:16 +01:00
int oldRoomId = 0;
ifs >> oldRoomId;
mRoomIdHash[mProfileName] = oldRoomId;
}
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
if (mVersion >= 11 && mVersion <= 20) {
// After version 20 the map labels have been moved to each area
int areasWithLabelsTotal = 0;
ifs >> areasWithLabelsTotal;
int areasWithLabelsCounter = 0;
while (!ifs.atEnd() && areasWithLabelsCounter < areasWithLabelsTotal) {
int areaID = -1;
int areaLabelsTotal = 0;
ifs >> areaLabelsTotal;
// Only used to identify the area for this batch of labels:
2011-06-26 23:26:24 +02:00
ifs >> areaID;
int areaLabelCounter = 0;
auto pA = mpRoomDB->getArea(areaID);
while (!ifs.atEnd() && areaLabelCounter < areaLabelsTotal) {
2021-04-02 19:10:16 +01:00
int labelID = 0;
2011-06-26 23:26:24 +02:00
ifs >> labelID;
TMapLabel label;
if (mVersion >= 12) {
// From version 12 labels could be placed on any level,
// so they have a z coordinate:
ifs >> label.pos;
} else {
QPointF labelPos2D;
ifs >> labelPos2D;
label.pos = QVector3D(labelPos2D);
}
// There was an unused QPointF in versions prior to 21
QPointF dummyPointF;
ifs >> dummyPointF;
2011-06-26 23:26:24 +02:00
ifs >> label.size;
ifs >> label.text;
ifs >> label.fgColor;
ifs >> label.bgColor;
ifs >> label.pix;
if (mVersion >= 15) {
2012-12-29 02:16:28 +01:00
ifs >> label.noScaling;
ifs >> label.showOnTop;
}
if (pA) {
restoreLabelFontFromUserData(label, labelID, pA->mUserData);
restoreLabelOutlineColorFromUserData(label, labelID, pA->mUserData);
pA->mMapLabels.insert(labelID, label);
}
++areaLabelCounter;
// Else: we dump labels for areas not in map - this should
// not be happening nowadays but did in the past - see
// PR #4369
2011-06-26 23:26:24 +02:00
}
++areasWithLabelsCounter;
2011-06-26 23:26:24 +02:00
}
}
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
while (!ifs.atEnd()) {
2021-04-02 19:10:16 +01:00
int i = 0;
2010-08-25 00:41:43 +02:00
ifs >> i;
improve: improve memory safety by using smart pointers (#9239) ### Refactor: replace raw pointer ownership with smart pointers across core subsystems #### Brief overview of PR changes/additions Replaces raw pointer ownership patterns with `std::unique_ptr` and `std::map` across several core subsystems: - **Host**: `mStopWatchMap` (`QMap<int, stopWatch*>` → `std::map<int, unique_ptr<stopWatch>>`), `profileShortcuts` (`QMap<QString, QKeySequence*>` → `std::map<QString, unique_ptr<QKeySequence>>`). Removes `qDeleteAll` in destructor and `delete mMMCPServer`. - **TMap**: `mpRoomDB` raw pointer → `unique_ptr` - **VarUnit**: `base` raw pointer → `unique_ptr` - **TTrigger**: condition map storage converted to `unique_ptr`, destructor simplified - **discord**: handler and presence maps converted from raw pointer `QMap` to `unique_ptr` + `std::map` - **Updater**: `mFeed` and `mUpdateDialog` converted to `unique_ptr` #### Motivation for adding to Mudlet These patterns were identified as sources of memory leaks and potential use-after-free bugs. Using smart pointers makes ownership explicit, eliminates manual cleanup code, and ensures correct destruction even on early-exit paths. #### Other info (issues closed, discussion etc) sorry this one is still pretty big, but most of the changes are the same for each thing so reviewing them together probably makes sense. sadly there isn't much to see here other than no slow uptick of heap size :-[ Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:42:09 +12:00
auto pT = new TRoom(mpRoomDB.get());
pT->restore(ifs, i, mVersion);
mpRoomDB->restoreSingleRoom(i, pT);
2010-08-25 00:41:43 +02:00
}
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
Infrastructure: move away from constructor initialisation lists - part 2 (#5937) For classes from "T2*" to "TM*" (approximately)... I have steered away from using `{}` to initialise simple, POD data types in favour of explicitly stating what their default values are. Also: * remove unused `(QColor) TAction::mButtonColor` and it's associated getter and setter. Also remove the save code from the `XMLexport` class and ensure it is skipped and silently discarded in the load code in `XMLimport`. * Make `private` some members of the `TFlipButton` class that probably weren't ever intended to be `public` * Remove unneeded named argument for `lua_State*` type in many (but not all) function declarations in `TLuaInterpreter.h` file - they aren't needed and whether an `L` was present or not seems to entirely down to the whim of the individual coder of each function...! * Rejig some of the initiliasations in the `TLuaInterpreter` class * Refactor a chunk of code n the `TMap` class used to (re)initialise the 16 colours user settable from the preferences dialogue to a method: `(void) TMap::restore16ColorSet()` - so that it can be used in three other places as well as the constuctor. * Remove unused `(int) T2DMap::gzoom`. * Add missing `TMediaData.h` file to qmake project file. Note: `QPointer<T>` instances do NOT need initialisation, they are automagically instantiated with a `nullptr` value. Revised to change code to fit in with PR #6133 There were some pre-Qt 5.14.0 version checks that are no longer relevant. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2022-06-27 20:36:51 +01:00
restore16ColorSet();
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
// Recalculate area bounds to fix any corrupted yminForZ/ymaxForZ values
// from older map files (bug where first room's Y wasn't negated)
const QList<int> areaIds = mpRoomDB->getAreaIDList();
for (int areaId : areaIds) {
TArea* pA = mpRoomDB->getArea(areaId);
if (pA) {
pA->calcSpan();
}
}
const QString okMsg = tr("[ INFO ] - Successfully read the map file (%1s), checking some\n"
2021-04-02 19:10:16 +01:00
"consistency details...")
.arg(_time.nsecsElapsed() * 1.0e-9, 0, 'f', 2);
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
postMessage(okMsg);
appendErrorMsgWithNoLf(okMsg);
if (canRestore) {
2010-08-25 00:41:43 +02:00
return true;
}
}
Enhance: add Area & Map user data structures & Lua script access commands Whilst working on the XML importer for Map files I found that I wanted some where to store the data from attributes for tags that we don't use in Mudlet directly. For room related details I could use the TRoom::userData member but then I realised that there is nothing corresponding to Areas or for the Map overall. This separate commit provides these and the lua commands to interact with them - with functionality the same as the Room based one. Of course, as there is only ONE map there is no argument needed to select an instance for those commands. Of all the "room" user data commands replicated for "area" and "map" the only one NOT so done are get????UserDataKeys() as this is a bit pointless with a getAll????UserData() one from which the keys could be extracted from the returned table {???? being "Area" or "Map"}. Added to TLuaInterpreter class to provide following user script commands: searchAreaUserData((string)<key>[, (string)<value>]) setAreaUserData((number)<area Id>, (string)<key>, (string)<value>) clearAreaUserData((number)<area Id>) clearAreaUserDataItem((number)<area Id>, (string)<key>) getAreaUserData((number)<area Id>, (string)<key>) getAllAreaUserData((number)<area Id>) setMapUserData((string)<key>, (string)<value>) clearMapUserData((string)<key>) clearMapUserDataItem() getMapUserData((string)<key>) getAllMapUserData() Refactored TMap::serialize() to allow saving in different map file formats as defined by the constants TMap::mDefaultVersion, mMinVersion and mMaxVersion - if either of the last pair are less than or more than the first value respectively then a control on the "Special Options" tab of the profile preferences dialog will be enabled - the state of each value that is allowed is clearly indicated and it is defaulted appropriately. At present: TMap::mDefaultVersion is 16 (replaces #define CURRENT_MAP_VERSION) TMap::mMinVersion is also 16 TMap::mMaxVersion is 17 This means that the new user data areas will only persist (be saved) if that control is manually adjusted to 17 FOR EACH SESSION in this development version. When we get to a release version mDefaultVersion should be upped to 17 so that the release version uses the new format but can be manually downgraded to current (16) for those who want to share a map with users who have not upgraded - with the less of those new user data items - such users can do this by opening the profile preferences, downing this setting THEN using the SAVE MAP button and then restoring to the default value and SAVING AGAIN to a different name in the recommend format. Also renamed TMap::version to TMap::mVersion... ========================================================================== As this code requires the revision to the map file format that is coded for but only enabled manually the setter commands setAreaUserData(...) and setMapUserData(...) will both emit a warning message that the data written will not CURRENTLY be saved with the map the FIRST (and only the first) time they are used when the preference control has not been manually adjusted. ========================================================================== Also: Tweaked a recent, previous merged commit that set an optional minimum time for a Timer NOT to display it's contents every time it fires in debug output screen in value: Host::mTimerDebugOutputSuppressionInterval so that the QTimeEdit that controls it defaults to adjusting the "Seconds" time field rather than the default "Hours" one as that is the one that is most likely the one the user might wist to use. Also: The control this commit adds to the Profile Preferences dialog makes use of the QComboBox::currentData() method that was introduced in Qt5.2 - the minimum Qt library requirement in the qmake project file was revised to accomodate this - if builders wish to use a Qt5.x before this they will need to manually provide extra code to allocate an integer value from the range of values wanted/offered. Also: whilst cross-checking for the cmake project file I found the top level one was missing from the qmake project file - so have added it to that. HOWEVER I HAVE NOT FOUND A WAY TO REQUIRE THE CMAKE SYSTEM TO REQUIRE QT5.2 AS A MINIMUM WHICH THIS COMMIT REQUIRES. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Conflicts: src/src.pro
2015-12-30 13:42:41 +00:00
return canRestore; //FIXME
2010-08-25 00:41:43 +02:00
}
// Reads the newest map file from the profile and retrieves some stats and data,
// including the current player room - was mRoomId in 12 to pre-18 map files and
// is in mRoomIdHash since then so that it can be reinserted into a map that is
// copied across (if the room STILL exists)! This is to avoid a replacement map
// (copied/shared) from one profile to another from repositioning the other
// player location. Though this is written as a member function it is intended
// also for use to retrieve details from maps from OTHER profiles, importantly
// it does (or should) NOT interact with this TMap instance...!
bool TMap::retrieveMapFileStats(QString profile, QString* latestFileName = nullptr, int* fileVersion = nullptr, int* roomId = nullptr, qsizetype* areaCount = nullptr, qsizetype* roomCount = nullptr)
{
if (profile.isEmpty()) {
return false;
}
QString folder;
QStringList entries;
folder = mudlet::getMudletPath(enums::profileMapsPath, profile);
QDir dir(folder);
dir.setSorting(QDir::Time);
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
entries = dir.entryList(QDir::Filters(QDir::Files | QDir::NoDotAndDotDot), QDir::Time);
if (entries.isEmpty()) {
return false;
}
// As the files are sorted by time this gets the latest one
QFile file(qsl("%1/%2").arg(folder, entries.at(0)));
if (!file.open(QFile::ReadOnly)) {
const QString errMsg = tr(R"([ ERROR ] - Unable to open map file for reading: "%1"!)").arg(file.fileName());
appendErrorMsg(errMsg, false);
postMessage(errMsg);
return false;
}
if (latestFileName) {
*latestFileName = file.fileName();
}
int otherProfileVersion = 0;
QDataStream ifs(&file);
BugFix ameliorate Qt changes to binary formats for QDataStream (#3133) * BugFix ameliorate Qt changes to binary formats for QDataStream In other words - fix https://github.com/Mudlet/Mudlet/issues/3088 ...! This forces the binary file format to be that which is used for Qt 5.12 if the run-time version of the Qt libraries are Qt 5.13 or later. This is needed to handle a change in the format that QFonts are saved/loaded in a binary form in a QDataStream but it also clamps the binary format to be equivalent to QDataStream::Qt_5_12 everywhere I could see it used so that future Mudlet versions do not suffer further issues going forward when Qt revise the QDataStream format for the classes it handles. This should also close https://github.com/Mudlet/Mudlet/issues/785 ! NOTE: THIS WILL BREAK THINGS TEMPORARILY FOR USERS OF MUDLET VERSIONS AFTER 4.0.1 OR THOSE WHO HAVE MANUALLY SET THE FILE FORMAT ON THEIR MAP TO BE VERSION 19 OR HIGHER AND HAVE MOVED BETWEEN A MUDLET USING A RUN-TIME QT VERSION LESS THAN QT 5.13 AND ONE USING THAT OR LATER. IT WILL LIKELY CAUSE EXISTING MAP FILE CONTENTS TO BECOME GARBAGE WHEN READ BY A MUDLET VERSION INCLUDING THIS PULL-REQUEST - SO IT IS NECESSARY TO OPEN ANY WANTED VERSION 19 OR LATER MAP FILES IN THE CURRENT (BUGGY) QT 5.13 OR LATER USING MUDLET AND RESAVE IT IN MUDLET FILE FORMAT 18 BEFORE UPGRADING TO A MUDLET WITH THIS PULL-REQUEST INCLUDED. ONCE THE MAP IS THEN LOADED IN THE NEWER MUDLET IT CAN BE RESET TO THE LATEST MAP FORMAT - and we should avoid similar Qt library change induced problems in the future. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2019-09-29 23:41:58 +02:00
if (mudlet::scmRunTimeQtVersion >= QVersionNumber(5, 13, 0)) {
ifs.setVersion(mudlet::scmQDataStreamFormat_5_12);
}
ifs >> otherProfileVersion;
const QString infoMsg = tr(R"([ INFO ] - Checking map file "%1", format version "%2".)").arg(file.fileName()).arg(otherProfileVersion);
appendErrorMsg(infoMsg, false);
if (mudlet::self()->showMapAuditErrors()) {
postMessage(infoMsg);
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
}
if (otherProfileVersion > mDefaultVersion) {
if (mudlet::self()->releaseVersion || mudlet::self()->publicTestVersion) {
// This is a release/public test version - should not support any map file versions higher that it was built for
if (fileVersion) {
*fileVersion = otherProfileVersion;
}
file.close();
return true;
}
// Is a development version so check against mMaxVersion
if (otherProfileVersion > mMaxVersion) {
// Oh dear, can't handle THIS
if (fileVersion) {
*fileVersion = otherProfileVersion;
}
file.close();
return true;
}
if (fileVersion) {
*fileVersion = otherProfileVersion;
}
} else {
if (fileVersion) {
*fileVersion = otherProfileVersion;
}
}
if (otherProfileVersion >= 4) {
// envColorMap
QMap<int, int> _dummyQMapIntInt;
ifs >> _dummyQMapIntInt;
// AreaNamesMap
QMap<int, QString> _dummyQMapIntQString;
ifs >> _dummyQMapIntQString;
}
if (otherProfileVersion >= 5) {
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
// mCustomEnvColors
QMap<int, QColor> _dummyQMapIntQColor;
ifs >> _dummyQMapIntQColor;
}
if (otherProfileVersion >= 7) {
// hashToRoomID
QMap<QString, int> _dummyQMapQStringInt;
ifs >> _dummyQMapQStringInt;
}
if (otherProfileVersion >= 17) {
// userMapData
QMap<QString, QString> _dummyQMapQStringQString;
ifs >> _dummyQMapQStringQString;
fix: Copy Map to inactive profiles losing player room position (#9091) #### Brief overview of PR changes/additions Add missing reads for mMapSymbolFont, mMapSymbolFontFudgeFactor, and mIsOnlyMapSymbolFontToBeUsed in retrieveMapFileStats() for map format v>=19, matching what restore() already does correctly #### Motivation for adding to Mudlet Copying a map to inactive profiles via Preferences silently corrupts the player's saved room position in those profiles because retrieveMapFileStats() reads garbage data from a desynchronized QDataStream. #### Other info (issues closed, discussion etc) The bug was introduced in 2016 (94dd41bfb7) when retrieveMapFileStats was written, and became active when map format v19 added three new fields (mMapSymbolFont, mMapSymbolFontFudgeFactor, mIsOnlyMapSymbolFontToBeUsed) to the serialization in serialize()/restore() but retrieveMapFileStats was never updated to match. The serialize() function writes in this order for v>=19: 1. mUserData 2. mMapSymbolFont (QFont) 3. mMapSymbolFontFudgeFactor (double) 4. mIsOnlyMapSymbolFontToBeUsed (bool) 5. area count + area data 6. room data 7. userRoomHash (contains the player room ID per profile) The restore() function reads all of these correctly (lines 1664-1677). But retrieveMapFileStats() read mUserData and then jumped straight to reading area count, interpreting the QFont bytes as an int. This desynchronized the entire QDataStream, causing all subsequent reads (area count, room count, player room ID) to return garbage. The only caller is dlgProfilePreferences.cpp:2741, the Copy Map feature for inactive profiles. It uses the returned roomId to update mRoomIdHash for the target profile. With the desync, this was either a garbage room ID (silently teleporting the player to a wrong room) or 0 (losing their position entirely). Since the default map save version is 20, this affected every map file written by current Mudlet. Active profiles were unaffected because their room ID is read from memory, not from disk. **Test case:** Create two profiles (A and B) each with a map. Close profile B. In profile A, go to Preferences, Mapper tab, click Copy Map. Check the debug output for profile B's stats -- area count and room count should now show correct values instead of garbage numbers. Reopen profile B and verify the player is in the correct room.
2026-03-22 14:03:43 +01:00
if (otherProfileVersion >= 19) {
QFont _dummyQFont;
ifs >> _dummyQFont;
double _dummyDouble;
ifs >> _dummyDouble;
bool _dummyBool;
ifs >> _dummyBool;
}
}
if (otherProfileVersion >= 14) {
int readAreaSize;
ifs >> readAreaSize;
qsizetype areaSize = static_cast<qsizetype>(readAreaSize);
if (areaCount) {
*areaCount = areaSize;
}
// read each area
for (qsizetype i = 0; i < areaSize; ++i) {
TArea pA(nullptr, nullptr);
int areaID;
ifs >> areaID;
ifs >> pA.rooms;
ifs >> pA.zLevels;
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
ifs >> pA.mAreaExits;
ifs >> pA.gridMode;
ifs >> pA.max_x;
ifs >> pA.max_y;
ifs >> pA.max_z;
ifs >> pA.min_x;
ifs >> pA.min_y;
ifs >> pA.min_z;
ifs >> pA.span;
if (otherProfileVersion >= 17) {
ifs >> pA.xmaxForZ;
ifs >> pA.ymaxForZ;
ifs >> pA.xminForZ;
ifs >> pA.yminForZ;
} else {
QMap<int, int> dummyMinMaxForZ;
ifs >> pA.xmaxForZ;
ifs >> pA.ymaxForZ;
ifs >> dummyMinMaxForZ;
ifs >> pA.xminForZ;
ifs >> pA.yminForZ;
ifs >> dummyMinMaxForZ;
}
ifs >> pA.pos;
ifs >> pA.isZone;
ifs >> pA.zoneAreaRef;
Improve: remember 2D mapper zoom amounts between sessions (#6615) This is intended to close #2388. This enables the 2D (only) map zoom amounts for each map area to be save independently and restored when switching between areas in the mapper. It also saves the data between session. It extends the existing `setMapZoom(...)` API to take an optional second argument to specify the map area ID to set the zoom (which is a floating point number) for any existing area, not just the current one. It also adds a `getMapZoom(...)` function that, without any arguments, returns the currently used 2D map zoom value for the area currently being shown in the 2D mapper. If an area ID is provided it instead returns the value that was last used for that area - or the default value that is used initially on starting the profile or for an area that has not been viewed before. Importantly when switching between the areas in the 2D mapper the values are retained and applied so that one area can be zoomed in and another zoomed out and switching from the first to the second and back to the first means that the zoom level used in the first is reused when it is returned to. Deleting an area will forget the stored zoom level so if it is reused it starts from scratch. Code to save the zoom level for each area has also been implemented within the C++ core. It saves it in the Area User Data for current map formats (but removes it on loading so the user never sees it there) under a `system.fallback_map2DZoom` key but will save it directly in the binary data (which is more efficient) in the next format version whenever it is enabled. A new Mudlet event, which has been called `sysMapAreaChanged` has been added with two additional arguments being the area ID changed to followed by the one that it was changed from. I originally thought I would need it to handle saving the zoom level for each area via the Lua system but I found that that was not practicable. Also, in refactoring `T2DMap::paintEvent(...)` I: Removed/combined some locals: * `(TArea*) playerArea` and `pPlayerArea` and `pArea`==> `pDrawnArea` * `(TRoom*) playerRoom` ==> `pPlayerRoom` Remove unneeded (refactored out): * `(qreal) ox` * `(qreal) oy` Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2023-03-16 15:00:33 +00:00
if (otherProfileVersion >= 21) {
ifs >> pA.mLast2DMapZoom;
}
if (otherProfileVersion >= 17) {
ifs >> pA.mUserData;
}
if (otherProfileVersion >= 21) {
int mapLabelsCount = -1;
ifs >> mapLabelsCount;
for (int i = 0; i < mapLabelsCount; ++i) {
int labelId = -1;
ifs >> labelId;
TMapLabel label;
ifs >> label.pos;
ifs >> label.size;
ifs >> label.text;
ifs >> label.fgColor;
ifs >> label.bgColor;
ifs >> label.pix;
ifs >> label.noScaling;
ifs >> label.showOnTop;
}
}
}
}
if (otherProfileVersion >= 18) {
// In version 18 we changed to store the "userRoom" for each profile
// so that when copied/shared between profiles they do not interfere
// with each other's saved value
QHash<QString, int> _dummyQHashQStringInt;
ifs >> _dummyQHashQStringInt;
if (roomId) {
*roomId = _dummyQHashQStringInt.value(profile);
}
} else if (otherProfileVersion >= 12) {
int oldRoomId;
ifs >> oldRoomId;
if (roomId) {
*roomId = oldRoomId;
}
} else {
if (roomId) {
*roomId = -1; // Not found value
}
}
if (otherProfileVersion >= 11 && otherProfileVersion <= 20) {
int areasWithLabelsTotal = 0;
ifs >> areasWithLabelsTotal;
int areasWithLabelsCounter = 0;
while (!ifs.atEnd() && areasWithLabelsCounter < areasWithLabelsTotal) {
int areaID = -1;
int areaLabelsTotal = 0;
ifs >> areaLabelsTotal;
ifs >> areaID;
int areaLabelCounter = 0;
while (!ifs.atEnd() && areaLabelCounter < areaLabelsTotal) {
int labelID;
ifs >> labelID;
TMapLabel label;
if (otherProfileVersion >= 12) {
ifs >> label.pos;
} else {
QPointF oldLabelPos;
ifs >> oldLabelPos;
label.pos = QVector3D(oldLabelPos);
}
QPointF dummyPointF;
ifs >> dummyPointF;
ifs >> label.size;
ifs >> label.text;
ifs >> label.fgColor;
ifs >> label.bgColor;
ifs >> label.pix;
if (otherProfileVersion >= 15) {
ifs >> label.noScaling;
ifs >> label.showOnTop;
}
++areaLabelCounter;
}
++areasWithLabelsCounter;
}
}
TRoom _pT(nullptr);
QSet<int> _dummyRoomIdSet;
while (!ifs.atEnd()) {
int i;
ifs >> i;
_pT.restore(ifs, i, otherProfileVersion);
// Can't do mpRoomDB->restoreSingleRoom( ifs, i, pT ) as it would mess up
// this TMap::mpRoomDB
// So emulate using _dummyRoomIdSet
if (i > 0 && !_dummyRoomIdSet.contains(i)) {
_dummyRoomIdSet.insert(i);
}
}
if (roomCount) {
*roomCount = _dummyRoomIdSet.count();
}
return true;
}
2010-08-25 00:41:43 +02:00
//NOLINT(readability-make-member-function-const)
int TMap::createMapLabel(int area,
const QString& text,
float x,
float y,
float z,
QColor fg,
QColor bg,
bool showOnTop,
bool noScaling,
bool temporary,
qreal zoom,
int fontSize,
std::optional<QString> fontName,
QColor outline)
2011-06-26 15:23:37 +02:00
{
auto pA = mpRoomDB->getArea(area);
if (!pA) {
return -1;
}
if (text.isEmpty()) {
return -1;
}
2011-06-26 15:23:37 +02:00
TMapLabel label;
label.text = text;
label.bgColor = bg;
label.fgColor = fg;
label.outlineColor = outline;
label.size = QSizeF(100, 100);
label.pos = QVector3D(x, y, z);
label.showOnTop = showOnTop;
label.noScaling = noScaling;
label.temporary = temporary;
const QRectF lr = QRectF(0, 0, 2000, 2000);
QPixmap pix(lr.size().toSize());
pix.fill(Qt::transparent);
QPainter lp(&pix);
lp.fillRect(lr, label.bgColor);
lp.setRenderHint(QPainter::Antialiasing);
QFont font(fontName.has_value() ? fontName.value() : QString(), fontSize);
label.font = font;
lp.setFont(font);
QPen outlinePen(label.outlineColor);
outlinePen.setWidth(1);
lp.setPen(outlinePen);
QRectF br;
if (label.fgColor != label.outlineColor) {
lp.drawText(QRect(19, 70, 2000, 2000), Qt::AlignLeft | Qt::AlignTop, label.text, &br);
lp.drawText(QRect(21, 70, 2000, 2000), Qt::AlignLeft | Qt::AlignTop, label.text, &br);
lp.drawText(QRect(20, 69, 2000, 2000), Qt::AlignLeft | Qt::AlignTop, label.text, &br);
lp.drawText(QRect(20, 71, 2000, 2000), Qt::AlignLeft | Qt::AlignTop, label.text, &br);
}
lp.setPen(label.fgColor);
lp.drawText(QRect(20, 70, 2000, 2000), Qt::AlignLeft | Qt::AlignTop, label.text, &br);
label.size = br.normalized().size();
const QRect brRect = br.normalized().toRect();
label.pix = pix.copy(brRect.topLeft().x(), brRect.topLeft().y(), brRect.width(), brRect.height());
const QSizeF s = QSizeF(label.size.width() / zoom, label.size.height() / zoom);
label.size = s;
label.clickSize = s;
2017-04-17 21:35:44 -07:00
const int labelId = pA->createLabelId();
if (Q_LIKELY(labelId >= 0)) {
pA->mMapLabels.insert(labelId, label);
if (mpMapper) {
mpMapper->mp2dMap->update();
}
2011-06-26 23:26:24 +02:00
}
if (!temporary) {
setUnsaved(__func__);
}
return labelId;
2011-06-26 15:23:37 +02:00
}
int TMap::createMapImageLabel(int area, QString imagePath, float x, float y, float z, float width, float height, float zoom, bool showOnTop, bool temporary)
{
auto pA = mpRoomDB->getArea(area);
if (!pA) {
return -1;
}
TMapLabel label;
label.size = QSizeF(width, height);
label.pos = QVector3D(x, y, z);
label.showOnTop = showOnTop;
// This method is only called from the TLuaInterpreter class and the value
// passed was hard-coded to this value:
label.noScaling = false;
label.temporary = temporary;
const QRectF drawRect = QRectF(0, 0, static_cast<qreal>(width * zoom), static_cast<qreal>(height * zoom));
const QPixmap imagePixmap = QPixmap(imagePath);
QPixmap pix = QPixmap(drawRect.size().toSize());
pix.fill(Qt::transparent);
QPainter lp(&pix);
lp.drawPixmap(QPoint(0, 0), imagePixmap.scaled(drawRect.size().toSize()));
label.size = QSizeF(width, height);
label.pix = pix;
2017-04-16 22:33:35 -07:00
const int labelId = pA->createLabelId();
if (Q_LIKELY(labelId >= 0)) {
pA->mMapLabels.insert(labelId, label);
if (mpMapper) {
mpMapper->mp2dMap->update();
}
}
if (!temporary) {
setUnsaved(__func__);
}
return labelId;
}
void TMap::deleteMapLabel(int area, int labelId)
2011-06-26 15:23:37 +02:00
{
auto pA = mpRoomDB->getArea(area);
if (!pA) {
return;
}
auto label = pA->mMapLabels.take(labelId);
if (!label.pos.isNull() || !label.text.isEmpty() || label.bgColor != QColorConstants::Black || label.fgColor != QColorConstants::Black) {
// If any of the above tests are false then we can take it that we do
// not have a "default constructed" label - i.e. a real one and not
// one that the QMap<T1, T2>::take(const T1&) has created for us in the
// absence of an actual TMapLabel.
// The TMapLabel default constructor sets the 'temporary' class member
// to false so we can safely rely on it being true for a temporary one:
if (!label.temporary) {
setUnsaved(__func__);
}
if (mpMapper) {
mpMapper->mp2dMap->update();
}
}
2011-06-26 15:23:37 +02:00
}
void TMap::postMessage(const QString text)
{
mStoredMessages.append(text);
Host* pHost = mpHost;
if (pHost) {
while (!mStoredMessages.isEmpty()) {
pHost->postMessage(mStoredMessages.takeFirst());
}
}
}
Enhance: make area selection widget centre map on room in middle of area As discussed in http://forums.mudlet.org/viewtopic.php?f=13&t=4818#p24498 this commit improves the way the centre of the view is selected when the area selection widget is used to (temporarily) show a view of a different area: * A) if the selected area has the same z-coordinate as the current view in the (2D) mapper then the mean coordinate of all the rooms on THAT level is calculated and then the room nearest to that is chosen to be at the centre of the view in the selected area. * B) if the selected area does not have any rooms on the same level then the level with the MOST rooms (and the lowest z coordinate if there are ties) is chosen and the room closest to the mean again selected. * C) if there are NOT rooms in the area then the view is centred on the origin. * D) if (after using the control more than once OR even if NOT) the original area is selected then the view snaps back to the current player room (this can be used to recenter on that if the scroll buttons have been used to offset the view!) The center of view position is made from code within the 2D mapper - but there is no need to do the same for the 3D one - instead the area ID and position is passed up to the TMap class instance which forwards the details to the 3D mapper. The bottom line is that (unless it is an empty area) a reasonable choice of room is ALWAYS displayed in the centre of the map when the area is changed manually (and the 2 and 3D maps will be centred on the same room). Code associated with loading maps has been refactored in an attempt to ensure that the area selection widget is set to the correct value before the first use by the user - there was four places where the map file was being loaded (although the one in the Host class constructor seems unnecessary - and problematic to handle as the Host class is instantiated before the mapper widget is created!) I *think* I have got it straight now but some testing in the map down load from server case may need a check to see that I have not broken anything. Also: * have tweaked the map information display to change the text format to emphasise when it reflects details of a selection (the text turns a bit orange and is written BOLD) or if the player room (which is what is referred to if NO rooms are selected) is in this area (the data is written in BOLD) or is not in the current area shown (the data is written in ITALICS and not bold). Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-04-28 23:48:08 +01:00
// Used by the 2D mapper to send view center coordinates to 3D one
void TMap::set3DViewCenter(const int areaId, const int xPos, const int yPos, const int zPos)
Enhance: make area selection widget centre map on room in middle of area As discussed in http://forums.mudlet.org/viewtopic.php?f=13&t=4818#p24498 this commit improves the way the centre of the view is selected when the area selection widget is used to (temporarily) show a view of a different area: * A) if the selected area has the same z-coordinate as the current view in the (2D) mapper then the mean coordinate of all the rooms on THAT level is calculated and then the room nearest to that is chosen to be at the centre of the view in the selected area. * B) if the selected area does not have any rooms on the same level then the level with the MOST rooms (and the lowest z coordinate if there are ties) is chosen and the room closest to the mean again selected. * C) if there are NOT rooms in the area then the view is centred on the origin. * D) if (after using the control more than once OR even if NOT) the original area is selected then the view snaps back to the current player room (this can be used to recenter on that if the scroll buttons have been used to offset the view!) The center of view position is made from code within the 2D mapper - but there is no need to do the same for the 3D one - instead the area ID and position is passed up to the TMap class instance which forwards the details to the 3D mapper. The bottom line is that (unless it is an empty area) a reasonable choice of room is ALWAYS displayed in the centre of the map when the area is changed manually (and the 2 and 3D maps will be centred on the same room). Code associated with loading maps has been refactored in an attempt to ensure that the area selection widget is set to the correct value before the first use by the user - there was four places where the map file was being loaded (although the one in the Host class constructor seems unnecessary - and problematic to handle as the Host class is instantiated before the mapper widget is created!) I *think* I have got it straight now but some testing in the map down load from server case may need a check to see that I have not broken anything. Also: * have tweaked the map information display to change the text format to emphasise when it reflects details of a selection (the text turns a bit orange and is written BOLD) or if the player room (which is what is referred to if NO rooms are selected) is in this area (the data is written in BOLD) or is not in the current area shown (the data is written in ITALICS and not bold). Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-04-28 23:48:08 +01:00
{
#if defined(INCLUDE_3DMAPPER)
if (mpM) {
Improve: add a new, experimental 3D mapper (#8087) <!-- Keep the title short & concise so anyone non-technical can understand it, the title appears in PTB changelogs --> #### Brief overview of PR changes/additions This adds an experimental, new 3D mapper that uses shaders, more modern openGL, and a far better code reorganization that makes it an easier foundation to build upon. The new 3D mapper is here side by side with the original and can be toggled on for experimentation. There's a lot of work to be done, so I'd rather merge it early instead of making a mega-PR. #### Motivation for adding to Mudlet So we have a new foundation to build upon and improve. #### Other info (issues closed, discussion etc) Old and new mapper can be toggled dynamically with: ```lua -- this can be a keybinding setConfig("experiment.3dmap.modernmapper", not getConfig("experiment.3dmap.modernmapper")) ``` Smooth movement is one experiment in the new mapper, and it can be enabled with: ```lua lua setConfig("experiment.rendering.smooth-camera", true) ``` As you notice an experiments system has been added so we can implement things at once and experiment to choose the one that works best. This system can be used in other places in Mudlet as well. <details><summary>Details</summary> <p> ## Experiments System ### Overview Allows enabling/disabling experimental features via `setConfig`/`getConfig` with validation against a predefined whitelist. ### Usage ```lua -- Enable experiment setConfig("experiment.rendering.more-transparent", true) -- Check if enabled local enabled = getConfig("experiment.rendering.more-transparent") -- returns true/false -- Get active experiment in group local active = getConfig("experiment.rendering.active") -- returns "more-transparent" -- List all valid experiments local experiments = getConfig("experiment.list") -- returns table of valid keys ``` ### Behavior - Grouped experiments: Mutually exclusive (enabling one disables others in same group) - Validation: Only predefined experiments allowed, invalid keys return errors - Persistence: Experiment states saved/loaded with profiles ### Adding New Experiments Edit Host::mValidExperiments in src/Host.cpp: ```cpp const QSet<QString> Host::mValidExperiments = { qsl("experiment.rendering.originalish"), qsl("experiment.rendering.more-transparent"), qsl("experiment.newfeature.option1"), // Add here }; ``` ### Current Experiments - experiment.rendering.originalish - experiment.rendering.more-transparent </p> </details> --------- Co-authored-by: Vadim Peretokin <vadi2@users.noreply.github.com>
2025-08-29 12:15:48 +02:00
if (auto* glWidget = dynamic_cast<GLWidget*>(mpM.data())) {
glWidget->setViewCenter(areaId, xPos, yPos, zPos);
} else if (auto* modernWidget = dynamic_cast<ModernGLWidget*>(mpM.data())) {
modernWidget->setViewCenter(areaId, xPos, yPos, zPos);
}
}
#else
Q_UNUSED(areaId)
Q_UNUSED(xPos)
Q_UNUSED(yPos)
Q_UNUSED(zPos)
#endif
Enhance: make area selection widget centre map on room in middle of area As discussed in http://forums.mudlet.org/viewtopic.php?f=13&t=4818#p24498 this commit improves the way the centre of the view is selected when the area selection widget is used to (temporarily) show a view of a different area: * A) if the selected area has the same z-coordinate as the current view in the (2D) mapper then the mean coordinate of all the rooms on THAT level is calculated and then the room nearest to that is chosen to be at the centre of the view in the selected area. * B) if the selected area does not have any rooms on the same level then the level with the MOST rooms (and the lowest z coordinate if there are ties) is chosen and the room closest to the mean again selected. * C) if there are NOT rooms in the area then the view is centred on the origin. * D) if (after using the control more than once OR even if NOT) the original area is selected then the view snaps back to the current player room (this can be used to recenter on that if the scroll buttons have been used to offset the view!) The center of view position is made from code within the 2D mapper - but there is no need to do the same for the 3D one - instead the area ID and position is passed up to the TMap class instance which forwards the details to the 3D mapper. The bottom line is that (unless it is an empty area) a reasonable choice of room is ALWAYS displayed in the centre of the map when the area is changed manually (and the 2 and 3D maps will be centred on the same room). Code associated with loading maps has been refactored in an attempt to ensure that the area selection widget is set to the correct value before the first use by the user - there was four places where the map file was being loaded (although the one in the Host class constructor seems unnecessary - and problematic to handle as the Host class is instantiated before the mapper widget is created!) I *think* I have got it straight now but some testing in the map down load from server case may need a check to see that I have not broken anything. Also: * have tweaked the map information display to change the text format to emphasise when it reflects details of a selection (the text turns a bit orange and is written BOLD) or if the player room (which is what is referred to if NO rooms are selected) is in this area (the data is written in BOLD) or is not in the current area shown (the data is written in ITALICS and not bold). Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-04-28 23:48:08 +01:00
}
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
void TMap::appendRoomErrorMsg(const int roomId, const QString msg, const bool isToSetFileViewingRecommended)
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
{
mMapAuditRoomErrors[roomId].append(msg);
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
mIsFileViewingRecommended = isToSetFileViewingRecommended ? true : mIsFileViewingRecommended;
}
void TMap::appendAreaErrorMsg(const int areaId, const QString msg, const bool isToSetFileViewingRecommended)
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
{
mMapAuditAreaErrors[areaId].append(msg);
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
mIsFileViewingRecommended = isToSetFileViewingRecommended ? true : mIsFileViewingRecommended;
}
void TMap::appendErrorMsg(const QString msg, const bool isToSetFileViewingRecommended)
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
{
mMapAuditErrors.append(msg);
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
mIsFileViewingRecommended = isToSetFileViewingRecommended ? true : mIsFileViewingRecommended;
}
void TMap::appendErrorMsgWithNoLf(const QString msg, const bool isToSetFileViewingRecommended)
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
{
QString text = msg;
text.replace(QChar::LineFeed, QChar::Space);
mMapAuditErrors.append(text);
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
mIsFileViewingRecommended = isToSetFileViewingRecommended ? true : mIsFileViewingRecommended;
}
const QString TMap::createFileHeaderLine(const QString title, const QChar fillChar)
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
{
QString text;
if (title.length() <= 76) {
text = qsl("%1 %2 %1\n").arg(QString(fillChar).repeated((78 - title.length()) / 2), title);
} else {
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
text = title;
text.append(QChar::LineFeed);
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
}
return text;
}
void TMap::pushErrorMessagesToFile(const QString title, const bool isACleanup)
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
{
Host* pHost = mpHost;
if (!pHost) {
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
qWarning() << "TMap::pushErrorMessagesToFile( ... ) ERROR: called with a NULL HOST pointer - something is wrong!";
return;
}
// Replacement storage locations:
QMap<int, QList<QString>> mapAuditRoomErrors; // Key is room number (where renumbered is the original one), Value is the errors, appended as they are found
QMap<int, QList<QString>> mapAuditAreaErrors; // As for the Room ones but with key as the area number
QList<QString> mapAuditErrors; // For the whole map
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
// Switch message storage locations to freeze them so we can dump them to
// file; according to Qt documentation "Swaps XXX other with this XXX. This
// operation is very fast and never fails."
mapAuditErrors.swap(mMapAuditErrors);
mapAuditAreaErrors.swap(mMapAuditAreaErrors);
mapAuditRoomErrors.swap(mMapAuditRoomErrors);
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
if (mapAuditErrors.isEmpty() && mapAuditAreaErrors.isEmpty() && mapAuditRoomErrors.isEmpty() && isACleanup) {
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
mIsFileViewingRecommended = false;
return; // Nothing to do
}
pHost->mErrorLogStream << createFileHeaderLine(title, QLatin1Char('#'));
pHost->mErrorLogStream << createFileHeaderLine(tr("Map issues"), QLatin1Char('='));
QListIterator<QString> itMapMsg(mapAuditErrors);
while (itMapMsg.hasNext()) {
pHost->mErrorLogStream << itMapMsg.next() << QLatin1Char('\n');
;
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
}
pHost->mErrorLogStream << createFileHeaderLine(tr("Area issues"), QLatin1Char('='));
QMapIterator<int, QList<QString>> itAreasMsg(mapAuditAreaErrors);
while (itAreasMsg.hasNext()) {
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
itAreasMsg.next();
QString titleText;
if (!mpRoomDB->getAreaNamesMap().value(itAreasMsg.key()).isEmpty()) {
titleText = tr(R"(Area id: %1 "%2")").arg(itAreasMsg.key()).arg(mpRoomDB->getAreaNamesMap().value(itAreasMsg.key()));
} else {
titleText = tr("Area id: %1").arg(itAreasMsg.key());
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
}
pHost->mErrorLogStream << createFileHeaderLine(titleText, QLatin1Char('-'));
QListIterator<QString> itMapAreaMsg(itAreasMsg.value());
while (itMapAreaMsg.hasNext()) {
pHost->mErrorLogStream << itMapAreaMsg.next() << QLatin1Char('\n');
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
}
}
pHost->mErrorLogStream << createFileHeaderLine(tr("Room issues"), QLatin1Char('='));
QMapIterator<int, QList<QString>> itRoomsMsg(mapAuditRoomErrors);
while (itRoomsMsg.hasNext()) {
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
itRoomsMsg.next();
QString titleText;
TRoom* pR = mpRoomDB->getRoom(itRoomsMsg.key());
if (pR && !pR->name.isEmpty()) {
titleText = tr(R"(Room id: %1 "%2")").arg(itRoomsMsg.key()).arg(pR->name);
} else {
titleText = tr("Room id: %1").arg(itRoomsMsg.key());
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
}
pHost->mErrorLogStream << createFileHeaderLine(titleText, QLatin1Char('-'));
QListIterator<QString> itMapRoomMsg(itRoomsMsg.value());
while (itMapRoomMsg.hasNext()) {
pHost->mErrorLogStream << itMapRoomMsg.next() << QLatin1Char('\n');
;
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
}
}
pHost->mErrorLogStream << createFileHeaderLine(tr("End of report"), QLatin1Char('#'));
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
pHost->mErrorLogStream.flush();
mapAuditErrors.clear();
mapAuditAreaErrors.clear();
mapAuditRoomErrors.clear();
if (mIsFileViewingRecommended && (!mudlet::self()->showMapAuditErrors())) {
postMessage(tr("[ ALERT ] - At least one thing was detected during that last map operation\n"
"that it is recommended that you review the most recent report in\n"
"the file:\n"
"\"%1\"\n"
"- look for the (last) report with the title:\n"
"\"%2\".")
.arg(mudlet::getMudletPath(enums::profileLogErrorsFilePath, mProfileName), title));
} else if (mIsFileViewingRecommended && mudlet::self()->showMapAuditErrors()) {
postMessage(tr("[ INFO ] - The equivalent to the above information about that last map\n"
"operation has been saved for review as the most recent report in\n"
"the file:\n"
"\"%1\"\n"
"- look for the (last) report with the title:\n"
"\"%2\".")
.arg(mudlet::getMudletPath(enums::profileLogErrorsFilePath, mProfileName), title));
Revision: route most of map auditing messages to errors.txt file As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2016-05-03 04:58:31 +01:00
}
mIsFileViewingRecommended = false;
}
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
void TMap::downloadMap(const QString& remoteUrl, const QString& localFileName)
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
{
fix: profile close during a map operation, Discord presence truncation, and interrupting ttsSpeak() (#9686) #### Brief overview of PR changes/additions - Closing a profile no longer frees the map out from under a running import, export or download. `TMap` counts the operations that pump `qApp->processEvents()`, and `mudlet::closeHost()` - which one of those pumps is what delivers it - stops the operation and destroys the `Host` once it has unwound, instead of half way through it. - Discord presence fields keep their last character and are only ever cut between characters: each buffer is now the documented limit plus room for its terminator, and a new `utils::copyUtf8String()` walks the cut back to a character boundary. - An interrupting `ttsSpeak()` announces the utterance it starts, and the `Ready` an engine reports for the utterance it cut off no longer drains `ttsQueue()` over the top of the one the script asked for. #### Motivation for adding to Mudlet Each is a filed defect, and each was reproduced before it was fixed. The map one is a use-after-free: ASan reports `heap-use-after-free` inside `TMap::readJsonMapFile()`, freed by `~TMap` <- `~Host` <- `HostManager::deleteHost` <- `mudlet::closeHost` delivered by the import's own `processEvents()`. The Discord one is worse than one field looking wrong: a single over-long non-ASCII field makes the whole `SET_ACTIVITY` payload undecodable, so the entire presence update is discarded - the fake Discord client recorded exactly that. The TTS one silently drops speech: `ttsQueue()` plus an interrupting `ttsSpeak()` speaks the queued line and never speaks the requested one. #### Other info (issues closed, discussion etc) Closes #9520, closes #9634, closes #9659. `MapCloseDuringImportTest` stages the close through `mudlet::slot_closeProfileByName()` and lets the map operation's own pump deliver it; the functional tests build with ASan, so the pre-fix run is a sanitizer report rather than an inference. `TtsInterruptingSpeakTest` hands `ttsStateChanged()` the `Ready` a real engine sends, which Qt's mock engine never does - the mock-visible half is pinned in `Media_spec.lua`, where the two specs that recorded the old behaviour are updated. `Discord_spec.lua` gains four end-to-end specs against `CI/discord-ipc-fixture.py` asserting that the captured frame still decodes as JSON and that a field is cut on a character boundary, and `DiscordTest.cpp` covers the same at unit level. Every new or changed test was confirmed to fail without its fix. Two things deliberately left alone, both older than this PR: `Host::requestClose()` still runs nested inside the map operation's pump (it saves the profile there), and an XML import or a map download has no cancel to poll, so a close waits for it rather than stopping it. **Test case:** Export a large map with `exportJsonMap()` and close the profile's tab while it runs; then `setDiscordDetail(string.rep("ä", 65))` and confirm the presence still updates; then `ttsQueue("queued line") ttsSpeak("first")` followed immediately by `ttsSpeak("second")` and confirm "second" is what gets spoken. Assisted-by: Claude:claude-opus-5
2026-08-07 06:10:42 +02:00
const MapOperationScope operationScope(this);
Host* pHost = mpHost;
if (!pHost) {
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
return;
}
// Incidentally this should address: https://bugs.launchpad.net/mudlet/+bug/852861
if (mImportRunning) {
const QString warnMsg = tr("[ WARN ] - Attempt made to download an XML map when one has already been\n"
"requested or is being imported from a local file - wait for that\n"
"operation to complete (if it cannot be canceled) before retrying!");
postMessage(warnMsg);
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
return;
}
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
if (mMapProgressStandalone) {
//: Shown in the main console when a map download is refused
const QString warnMsg = tr("[ WARN ] - Attempt made to download an XML map while a map import or\n"
"export is already in progress - wait for that operation to complete\n"
"before retrying!");
postMessage(warnMsg);
return;
}
mImportRunning = true;
// MUST clear this flag when done under ALL circumstances
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
QUrl url;
if (remoteUrl.isEmpty()) {
if (!getMmpMapLocation().isEmpty()) {
url = QUrl::fromUserInput(getMmpMapLocation());
} else {
url = QUrl::fromUserInput(qsl("https://www.%1/maps/map.xml").arg(pHost->mUrl));
}
} else {
url = QUrl::fromUserInput(remoteUrl);
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
if (!url.isValid()) {
const QString errMsg = tr("[ WARN ] - Attempt made to download an XML from an invalid URL. The URL was:\n"
"%1\n"
"and the error message (may contain technical details) was:"
"\"%2\".")
.arg(url.toString(), url.errorString());
postMessage(errMsg);
mImportRunning = false;
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
return;
}
// Check to ensure we have a map directory to save the map files to.
const QDir toProfileDir;
const QString toProfileDirPathString = mudlet::getMudletPath(enums::profileMapsPath, mProfileName);
if (!toProfileDir.mkpath(toProfileDirPathString)) {
const QString errMsg = tr("[ ERROR ] - Unable to use or create directory to store map.\n"
"Please check that you have permissions/access to:\n"
"\"%1\"\n"
"and there is enough space. The download operation has failed.")
.arg(toProfileDirPathString);
pHost->postMessage(errMsg);
mImportRunning = false;
return;
}
if (localFileName.isEmpty()) {
if (url.toString().endsWith(QLatin1String("xml"))) {
mLocalMapFileName = mudlet::getMudletPath(enums::profileXmlMapPathFileName, mProfileName);
} else {
mLocalMapFileName = mudlet::getMudletPath(enums::profileMapPathFileName, mProfileName, qsl("map.dat"));
}
} else {
mLocalMapFileName = localFileName;
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
QNetworkRequest request = QNetworkRequest(url);
pHost->updateProxySettings(mpNetworkAccessManager);
mudlet::self()->setNetworkRequestDefaults(url, request);
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
mExpectedFileSize = 4000000;
const QString infoMsg = tr("[ INFO ] - Map download initiated, please wait...");
postMessage(infoMsg);
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
qApp->processEvents();
// Attempts to ensure INFO message gets shown before download is initiated!
mpNetworkReply = mpNetworkAccessManager->get(request);
//: %1 is the name of the current Mudlet profile
const QString label = tr("Downloading map file for use in %1...").arg(mProfileName);
//: This is a title of a progress window.
createTransferProgress(tr("Map download"), label, true);
connect(mpNetworkReply, &QNetworkReply::downloadProgress, this, &TMap::slot_setDownloadProgress);
connect(mpNetworkReply, &QNetworkReply::errorOccurred, this, &TMap::slot_downloadError);
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
// Called from TLuaInterpreter::loadFile() or dlgProfilePreferences's "loadMap"
// both via TConsole::importMap( QFile & ) - it is intended to prevent
// readXmlMapFile( QFile & ) from being used more than once at a time and to
// prevent the above callers from using that when a map download is in progress!
// errMsg if, non-null is for a suitable structured error message to return to
// the TLuaInterpreter::loadFile(...) usage and is also needed to suppress the
// error message to the console
bool TMap::importMap(QFile& file, QString* errMsg)
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
{
if (mImportRunning) {
if (errMsg) {
*errMsg = tr("loadMap: unable to perform request, a map is already being downloaded or\n"
"imported at user request.");
} else {
const QString warnMsg = qsl("[ WARN ] - Attempt made to import an XML map when one is already being\n"
"downloaded or is being imported from a local file - wait for that\n"
"operation to complete (if it cannot be canceled) before retrying!");
postMessage(warnMsg);
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
return false;
}
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
if (mMapProgressStandalone) {
// readXmlMapFile() would see the JSON operation's progress dialog as its
// own, skip creating one, and then mapClear() the map out from under it:
if (errMsg) {
//: Error returned by the loadMap() Lua function
*errMsg = tr("loadMap: unable to perform request, a map import or export is\n"
"already in progress.");
} else {
//: Shown in the main console when a map import is refused
const QString warnMsg = tr("[ WARN ] - Attempt made to import an XML map while a map import or\n"
"export is already in progress - wait for that operation to complete\n"
"before retrying!");
postMessage(warnMsg);
}
return false;
}
mImportRunning = true;
// MUST clear this flag when done under ALL circumstances
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
const bool result = readXmlMapFile(file, errMsg);
mImportRunning = false;
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
return result;
}
bool TMap::readXmlMapFile(QFile& file, QString* errMsg)
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
{
fix: profile close during a map operation, Discord presence truncation, and interrupting ttsSpeak() (#9686) #### Brief overview of PR changes/additions - Closing a profile no longer frees the map out from under a running import, export or download. `TMap` counts the operations that pump `qApp->processEvents()`, and `mudlet::closeHost()` - which one of those pumps is what delivers it - stops the operation and destroys the `Host` once it has unwound, instead of half way through it. - Discord presence fields keep their last character and are only ever cut between characters: each buffer is now the documented limit plus room for its terminator, and a new `utils::copyUtf8String()` walks the cut back to a character boundary. - An interrupting `ttsSpeak()` announces the utterance it starts, and the `Ready` an engine reports for the utterance it cut off no longer drains `ttsQueue()` over the top of the one the script asked for. #### Motivation for adding to Mudlet Each is a filed defect, and each was reproduced before it was fixed. The map one is a use-after-free: ASan reports `heap-use-after-free` inside `TMap::readJsonMapFile()`, freed by `~TMap` <- `~Host` <- `HostManager::deleteHost` <- `mudlet::closeHost` delivered by the import's own `processEvents()`. The Discord one is worse than one field looking wrong: a single over-long non-ASCII field makes the whole `SET_ACTIVITY` payload undecodable, so the entire presence update is discarded - the fake Discord client recorded exactly that. The TTS one silently drops speech: `ttsQueue()` plus an interrupting `ttsSpeak()` speaks the queued line and never speaks the requested one. #### Other info (issues closed, discussion etc) Closes #9520, closes #9634, closes #9659. `MapCloseDuringImportTest` stages the close through `mudlet::slot_closeProfileByName()` and lets the map operation's own pump deliver it; the functional tests build with ASan, so the pre-fix run is a sanitizer report rather than an inference. `TtsInterruptingSpeakTest` hands `ttsStateChanged()` the `Ready` a real engine sends, which Qt's mock engine never does - the mock-visible half is pinned in `Media_spec.lua`, where the two specs that recorded the old behaviour are updated. `Discord_spec.lua` gains four end-to-end specs against `CI/discord-ipc-fixture.py` asserting that the captured frame still decodes as JSON and that a field is cut on a character boundary, and `DiscordTest.cpp` covers the same at unit level. Every new or changed test was confirmed to fail without its fix. Two things deliberately left alone, both older than this PR: `Host::requestClose()` still runs nested inside the map operation's pump (it saves the profile there), and an XML import or a map download has no cancel to poll, so a close waits for it rather than stopping it. **Test case:** Export a large map with `exportJsonMap()` and close the profile's tab while it runs; then `setDiscordDetail(string.rep("ä", 65))` and confirm the presence still updates; then `ttsQueue("queued line") ttsSpeak("first")` followed immediately by `ttsSpeak("second")` and confirm "second" is what gets spoken. Assisted-by: Claude:claude-opus-5
2026-08-07 06:10:42 +02:00
const MapOperationScope operationScope(this);
Host* pHost = mpHost;
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
bool isLocalImport = false;
if (!pHost) {
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
return false;
}
if (!hasActiveTransferProgress()) {
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
isLocalImport = true;
//: This is a title of a progress window.
createTransferProgress(tr("Map import"), tr("Importing XML map file for use in %1...").arg(mProfileName), false);
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
// It is NOW safe to delete the map as we are in a position to load one
mapClear();
XMLimport reader(pHost);
auto [success, message] = reader.importPackage(&file);
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
if (!mpMapper.isNull() && mpMapper->mp2dMap) {
// probably not needed for the download but might be
// needed for local file case:
mpMapper->mp2dMap->init();
// No need to call audit() as XMLimport::importPackage() does it!
// audit() produces the successful ending [ OK ] message...!
mpMapper->updateAreaComboBox();
if (success) {
mpMapper->resetAreaComboBoxToPlayerRoomArea();
} else {
// Failed...
if (errMsg) {
*errMsg = tr("loadMap: failure to import XML map file, further information may be available\n"
"in main console!");
}
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
}
if (!success && errMsg) {
*errMsg = tr("loadMap: failure to import XML map file, further information may be available\n"
"in main console!");
}
if (isLocalImport) {
clearTransferProgress();
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
if (!mpMapper.isNull()) {
mpMapper->show();
}
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
return success;
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
void TMap::slot_setDownloadProgress(qint64 got, qint64 total)
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
{
if (!hasActiveTransferProgress()) {
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
return;
}
if (!transferProgressMaximum()) {
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
// First call, range has not been set;
updateTransferProgressRange(0, mExpectedFileSize);
} else if (total != -1 && transferProgressMaximum() != static_cast<int>(total)) {
// total will stick at -1 when we do not know how big the download is
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
// which seems to be the case for the IRE MUDS - *sigh* - Slysven
updateTransferProgressRange(0, static_cast<int>(total));
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
updateTransferProgressValue(static_cast<int>(got));
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
void TMap::slot_downloadCancel()
{
const QString alertMsg = tr("[ ALERT ] - Map download was canceled, on user's request.");
postMessage(alertMsg);
clearTransferProgress();
if (mpNetworkReply) {
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
mpNetworkReply->abort(); // Will indirectly cause error() AND replyFinished signals to be sent
}
}
void TMap::slot_downloadError(QNetworkReply::NetworkError error)
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
{
if (!mpNetworkReply) {
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
return;
}
if (error != QNetworkReply::OperationCanceledError) {
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
// No point in reporting Cancel as that is handled elsewhere
const QString errMsg = tr("[ ERROR ] - Map download encountered an error:\n%1").arg(mpNetworkReply->errorString());
postMessage(errMsg);
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
}
void TMap::slot_replyFinished(QNetworkReply* reply)
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
{
auto cleanup = [this, reply]() {
reply->deleteLater();
mpNetworkReply = nullptr;
// We don't dismiss the progress display until here as we now use it to
// inform about post-download operations
clearTransferProgress();
mLocalMapFileName.clear();
mExpectedFileSize = 0;
// We have finished with the XMLimporter so must clear the flag
mImportRunning = false;
};
if (reply != mpNetworkReply) {
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
qWarning() << "TMap::slot_replyFinished( QNetworkReply * ) ERROR - received argument was not the expected stored pointer.";
}
if (reply->error() != QNetworkReply::NoError && reply->error() != QNetworkReply::OperationCanceledError) {
// Don't report on any errors here as we've already done so in slot_downloadError(...) previously.
cleanup();
return;
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
// else was QNetworkReply::OperationCanceledError and we already handle
// THAT in slot_downloadCancel()
}
// Separate the two kinds of files to gain QSaveFile's atomic write behavior
QSaveFile writeFile(mLocalMapFileName);
QFile readFile(mLocalMapFileName);
if (!writeFile.open(QFile::WriteOnly)) {
const QString alertMsg = tr("[ ALERT ] - Map download failed, unable to open destination file:\n%1.").arg(mLocalMapFileName);
postMessage(alertMsg);
cleanup();
return;
}
// The QNetworkReply is Ok here:
if (writeFile.write(reply->readAll()) == -1) {
const QString alertMsg = tr("[ ALERT ] - Map download failed, unable to write destination file:\n%1.").arg(mLocalMapFileName);
postMessage(alertMsg);
cleanup();
return;
}
if (!writeFile.commit()) {
const QString alertMsg = tr("[ ALERT ] - Map download failed, unable to save destination file:\n%1\nreason: %2").arg(mLocalMapFileName, writeFile.errorString());
postMessage(alertMsg);
cleanup();
return;
}
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
Host* pHost = mpHost;
if (!pHost) {
qWarning() << "TMap::slot_replyFinished( QNetworkReply * ) ERROR - NULL Host pointer - something is really wrong!";
cleanup();
return;
}
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
const QString infoMsg = tr("[ INFO ] - ... map downloaded and stored, now parsing it...");
postMessage(infoMsg);
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
// Since the download is complete but we do not offer to
// cancel the required post-processing we should now hide
// the cancel/abort button:
disableTransferProgressCancel();
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
bool parsingWasSuccessful;
QString parsingFileName;
if (!readFile.fileName().endsWith(qsl("xml"), Qt::CaseInsensitive)) {
parsingFileName = readFile.fileName();
parsingWasSuccessful = pHost->mpConsole->loadMap(parsingFileName);
} else {
parsingFileName = mLocalMapFileName;
if (!readFile.open(QFile::OpenMode(QFile::ReadOnly | QFile::Text))) {
const QString alertMsg = tr("[ ERROR ] - Map download problem, unable to read destination file:\n%1.").arg(parsingFileName);
postMessage(alertMsg);
cleanup();
return;
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
// The action to parse the XML file has been refactored to
// a separate method so that it can be shared with the
// direct importation of a local copy of a map file.
parsingWasSuccessful = readXmlMapFile(readFile);
readFile.close();
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
if (parsingWasSuccessful) {
TEvent mapDownloadEvent{};
mapDownloadEvent.mArgumentList.append(qsl("sysMapDownloadEvent"));
mapDownloadEvent.mArgumentTypeList.append(ARGUMENT_TYPE_STRING);
pHost->raiseEvent(mapDownloadEvent);
} else {
// Failure in parse file...
const QString alertMsg = tr("[ ERROR ] - Map download problem, failure in parsing destination file:\n%1.").arg(parsingFileName);
postMessage(alertMsg);
}
if (mpMapper) {
mpMapper->updateEmptyStateOverlay();
}
cleanup();
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
void TMap::reportStringToProgressDialog(const QString text)
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
{
if (hasActiveTransferProgress()) {
updateTransferProgressLabel(text);
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
// Needed to make the changed text show, it does increase the overall
// time a little but as the main usage is when parsing XML room data
// and that can take MORE THAN A MINUTE the activity is essential to
// inform the user that something IS happening...
qApp->processEvents();
}
}
void TMap::reportProgressToProgressDialog(const int current, const int maximum)
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
{
if (hasActiveTransferProgress()) {
if (transferProgressMaximum() != maximum) {
updateTransferProgressRange(0, maximum);
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
updateTransferProgressValue(current);
}
}
void TMap::createTransferProgress(const QString& title, const QString& label, bool cancelable)
{
if (mpMapper && mpMapper->isVisible()) {
mpMapper->showMapProgress(label, cancelable);
connect(mpMapper, &dlgMapper::signal_mapProgressCanceled, this, &TMap::slot_downloadCancel, Qt::UniqueConnection);
return;
}
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
mMapProgressStandalone = true;
mMapProgressIsTransfer = true;
mMapProgressCancelRequested = false;
mMapProgressStandaloneMaximum = 0;
warnIfMapProgressUnwired(__func__, true);
emit signal_mapTransferProgressStart(title, label, cancelable ? tr("Abort") : QString());
}
void TMap::updateTransferProgressLabel(const QString& text)
{
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
if (mMapProgressStandalone) {
emit signal_mapProgressSetLabel(text);
} else if (mpMapper) {
mpMapper->setMapProgressLabel(text);
}
}
void TMap::updateTransferProgressRange(int minimum, int maximum)
{
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
if (mMapProgressStandalone) {
mMapProgressStandaloneMaximum = maximum;
emit signal_mapProgressSetRange(minimum, maximum);
} else if (mpMapper) {
mpMapper->setMapProgressRange(minimum, maximum);
}
}
void TMap::updateTransferProgressValue(int value)
{
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
if (mMapProgressStandalone) {
emit signal_mapProgressSetValue(value);
} else if (mpMapper) {
mpMapper->setMapProgressValue(value);
}
}
int TMap::transferProgressMaximum() const
{
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
if (mMapProgressStandalone) {
return mMapProgressStandaloneMaximum;
}
if (mpMapper) {
return mpMapper->mapProgressMaximum();
}
return 0;
}
bool TMap::hasActiveTransferProgress() const
{
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
return mMapProgressStandalone || (mpMapper && mpMapper->isMapProgressVisible());
}
void TMap::disableTransferProgressCancel()
{
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
if (mMapProgressStandalone) {
emit signal_mapProgressDisableCancel();
} else if (mpMapper) {
mpMapper->setMapProgressCancelable(false);
}
}
void TMap::clearTransferProgress()
{
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
// Only close a transfer-owned standalone dialog: a concurrent JSON
// import/export owns the standalone progress state and must keep it.
if (mMapProgressStandalone && mMapProgressIsTransfer) {
mMapProgressStandalone = false;
mMapProgressIsTransfer = false;
emit signal_mapProgressClose();
return;
}
if (mpMapper) {
disconnect(mpMapper, &dlgMapper::signal_mapProgressCanceled, this, &TMap::slot_downloadCancel);
mpMapper->hideMapProgress();
Enhance: fix map downloading code, add manual XML map importing (#326) * Enhance: fix map downloading code, add manual XML map importing A recent move by I.R.E. to using SSL for their public MUD map URLs broke the ability for Mudlet to download those XML format files. This commit addresses this issue (as mentioned in, but not the original problem referred to in https://bugs.launchpad.net/mudlet/+bug/1427364) the revision to the code does now use "https://www.<MUD URL>/maps/map.xml" as a default name for the I.R.E. MUDS - however the method that initiates the download which was moved to TMap class from the dlgMapper one (see below) is now: (bool) TMap::downloadMap( const QString * remoteUrl = Q_NULLPTR, const QString * localFileName = Q_NULLPTR ) which if not supplied with any arguments behaves as before. However the remoteUrl argument may be given as a full QString including the scheme (the bit of the URL at the beginning before the ':') to override that and a second argument may be used to provide a different name to use for the local file name which if is a RELATIVE pathFileName will be resolved in relation to the profile directory. At present no use is made of this additional functionality but it may be useful for use with other MUDs if they should choose to provide XML map files with other remote locations and scripts using a different local filename. As a long-standing thing that needed doing I have finally provided a means to import a map XML file that - for instance - has already been download. It had been noted that there was no way to read those I.R.E. map files even if they had been obtained from a web browser able to correctly handle https: URLs - now both the TLuaInterpreter::loadMap() and the dlgProfilePreference "loadMap" button {NOT the IRE only "map download" one} will both handle files ending in ".xml" (not case sensitive so it'll work MacOS platforms as well!} For the loadMap case it will be necessary to change the filetype filter on the File Selection dialog to select "xml" files. During testing it became clear to me that it was possible to try and read one or more XML files via several mechanisms simultaneously with "unhelpful" consequences. As well as hitting the dlgProfilePreferences IRE "map download" multiple times, the TLuaInterpreter::loadMap() does NOT block until the map has been loaded and as the import time {running of XMLinport::readPackage(...)} is of significant duration for a large map (a debug, without optimisation, build on my 1.8GHz Quad-core took over two minutes to process the current Achaea map file) it is very possible to get conditions where the same profile will try to run XMLinport::readPackage(...) asynchronously - given that a profile only supports ONE map at a time it was necessary to fit a QMutex to prevent the part of the XMLinport class relating to XML Map files being called from different places in the map related code. This means that if a map download is started further downloads and any local map imports will fail until that first download has completed or aborted. Similarly a local import will prevent a download being started. As a side effect this cures: https://bugs.launchpad.net/mudlet/+bug/852861 - "Map download button starts another download thread if one is already going" The previous XML import code was not adding the rooms that it parsed to the relevant TArea::rooms member - although this would be picked-up and fixed by TMap::audit() later on, this would be accompanied by an error message about every single room. The code now builds up this information while parsing the rooms' details and inserts it so that this does not cause report-able problems during the TMap::audit() execution - the data gathered also allows missing areas to be spotted so that if a room claimed to belong to an area that was not included in the preceding areas' data an unnamed area is created for it. As a consequence of the long time to actually parse an XML map file I have enhanced the progress dialog that was originally used to track the map file download. It is now retained until the file is completely imported and shows more information about the process - importantly it shows during the XMLimport::readRoom(...) the room id being processed - and THAT method is the time/cpu hog so seeing something happening during the time that Mudlet otherwise appears to hang is useful feedback even if it adds a few seconds to the overall duration (may be more than a minute). This dialog is now also used during the other routes that involve reading an XML file and there is now a bit of consistence with the on-screen messages. Whilst inspecting XMLimport class I found there was some uncertain initialisation which I have tidied up. In summary: Added: * (bool) TConsole::importMap(const QString & location) * (void) TRoomDB::setAreaRooms(const int areaId, const QSet<int> & roomIds) * image file mudlet_map_download.png used as icon for download/import progress dialog * (bool) TMap::importMap(QFile & file) * (bool) TMap::readXmlMapFile(QFile & file) * (void) TMap::slot_downloadError(QNetworkReply::NetworkError error) * (void) TMap::reportStringToProgressDialog(const QString text) * (void) TMap::reportProgressToProgressDialog(const int current, const int maximum) Revised: * (int)TLuaInterpreter::loadMap( lua_State * ) * Moved XML map download code from dlgMapper class to the TMap one: + (void) dlgMapper::downloadMap() ==> (bool) TMap::downloadMap(const QString * remoteUrl, const QString * localFileName) + (void) dlgMapper::setDownloadProgress(qint64, qint64) ==> (void) TMap::slot_setDownloadProgress(qint64,qint64) + (void) dlgMapper::cancel() ==> (void) TMap::slot_downloadCancel() + (void) dlgMapper::replyFinished(QNetworkReply *) ==> (void) TMap::slot_replyFinished(QNetworkReply *) * Enhanced download progress indication to also include parsing which can take even more time than download! * Provide means to import local XML map file * Prevent trying to import/download more than one map at a time Renamed: * (void) XMLimport::readAreaNames() ==> XMLimport::readArea() - for consistency with related functions Commented out unused: * (void) XMLimport::readUnknownRoomElement() Note the movement of the map file download code to the TMap class does require making the latter a class with the Q_OBJECT macro (which removes the need for Q_DECLARE_TR_FUNCTIONS as a side-effect!) - though as another side-effect the TMap header needed a boost name specifier added to one identifier as that identifier ("property") exists in both boost and QObject classes!!! YOU MAY NEED TO RUN QMAKE ON THE PROJECT IF THE BUILD SYSTEM DOES NOT PICK UP THE ADDITION OF "Q_OBJECT" TO TMAP CLASS. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: Include missing #include, remove unused return value The absence of this was causing build errors on the Travis C.I. platform! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * BugFix: move TMap.h to mudlet_MOC_HDRS to fix CMake build issue As we have made TMap inherit from QOject - to have signal/slot functionality that class needs to be run through Qt's MOC - and to do that with the CMake project/build system it needs to be included in the files included in the projects *_MOC_HDRS {and removed from the *_HDRS} variable. Also spotted a trivial error in that specifying a const return value from method is ineffective and pointless - so removed it from: TMap::retrieveMapFileStats(QString,QString *,int *,int *,int *,int *) Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: clean up TMap initialisation/clearing actions Now restores the customEnvColors set up on initialisation but that was cleared when the map replaced with another one that is loaded {which subsequently replaces that element anyway} or imported {which merely writes over it, replacing any matching keys}. Initialises elements that when inspected on the entry to the constructor proper previously were not being set to a consistent value {booleans/ints/floats}. NOTE: This will now clear the map user data member when the map is cleared if the date is required to be saved when one map is loaded OR IMPORTED over an existing one then the data will need to be saved outside of the map - as is already need for areas and rooms user data! Also comment out or remove unused members/methods: * (void) TMap::getConnectedNodesGreaterThanX(int, int) * (void) TMap::getConnectedNodesSmallerThanX(int, int) * (void) TMap::getConnectedNodesGreaterThanY(int, int) * (void) TMap::getConnectedNodesSmallerThanY(int, int) * (void) TMap::astBreitenAnpassung(int, int) * (void) TMap::astHoehenAnpassung(int, int) * (void) TMap::exportMapToDatabase() * (void) TMap::importMapFromDatabase() * (QVector3D) TMap::span * (int) TMap::mViewArea * (QMap<QString, int>) TMap::pixNameTable * (QMap<int, QPixmap>) TMap::pixTable * (bool) TMap::isToDisplayAuditErrorsToConsole Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * ImplimentationFixes: activate a valid optimisation & remove redundant code Adding a true as a non-default 3rd argument to TRoomDB::addRoom(...) call in XMLimport::readRoom(...) enables a significant optimisation (skips a computationally expensive step when ADDING a room to new map) which dramatically reduces the time to parse an XML map file. It also pointed to the fact that the TRoomDB::entranceMap was already correctly being handled and didn't need to be regenerated in XMLimport::readRoom(...) so the code that was added in a previous commit was redundant and could be removed. A code error in TMap::slot_setDownloadProgress(...) that caused an issue that a reviewer found on test has been fixed - the total download filesize that was being sent by the Qt system signal that is connected to this slot was a -1 value (as IS DOCUMENTED) when the Qt system does NOT know the size of a QNetworkReply in advance of reaching the end of the download was incorrectly handled in a previous commit in this change set. Also found during testing that there is no need for an error message for the QNetworkReply::OperationCanceledError case in TMap::slot_replayFinished(...) as it is already handled in the TMap::slot_downloadCancel() slot. Changed the text put up onto the progress widget during the XML room parsing to be a room count - which is likely more useful and to only do it for every hundredth room - which reduces any delay "wasted" in writing to the display - combined, the effects seem satisfactory IMHO. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: provide error messages for TLuaInterpreter::loadMap(...) Errors for the XML map file importing process as initiated from the Lua command should be returned to that command rather than plastered onto the main profile console - this commit attempts to perform that effect. In testing found that there was no error handling for failure to find or open the nominated file so messages for that have been added as well. Due to the previous program logic the action of creating a mapper widget using the main toolbar button automatically loaded the "default" (the newest Mudlet Map file format file from the currently active profile's map sub-directory). Under some previous situations it looked as though a map might be loaded twice as mudlet::slot_mapper() was called both directly and via signal/slot action. These were resolved by turning that slot into a wrapper that now calls the body of code formerly within to a new method mudlet::createMapper( bool isToLoadDefaultMapFile = true ) with a the default value as an argument. This allows other usages of the body of code to be called directly with a suitable argument, which for the TConsole::loadMap() & TConsole::importMap() and the dlgProfilePreferences::downloadMap() cases is false as they are all do not want the "default" map! Also: * spotted a word "area" missing from an advisory text in TRoom::auditRooms(...). Signed-off-by: Stephen Lyons <slysven@virginmedia.com> * Tweak: fix minor bug, correct a spelling, undo a few capitalisations Under certain, unanticipated (error with no error message) conditions TLuaInterpreter::loadMap(...) would push both a nil and then a false value onto the stack for return {wrong} but only indicate one value {correct}. The textual matters were found during peer review. off-by: Stephen Lyons <slysven@virginmedia.com>
2016-10-13 09:18:48 +01:00
}
}
Enhance: add ability to set any glyph as a room symbol (#1543) This is a squashed down commit containing several commits with messages - this is the edited combination of all the messages: As well as being able to use any grapheme it is possible to use a short word as well as anything printable from any of the Unicode Multiple Planes; although the former will become smaller to fit within both the square and round room shapes on the 2D mapper. Adds controls to the profile preference to set the (preferred) font to use to set the room symbols from and a checkbox to only use that font. Additionally a sub-dialog can be brought up which lists the details of all the different symbols on the map - showing the Unicode codepoint(s) for each and showing how they would be rendered if only the selected font is used and if any font is permitted, along with a count of the usages and the rooms that use each one... A status icon is also displayed showing whether the symbol can be rendered entirely with the selected font (green tick), only by using glyphs from other fonts (yellow ! warning) or not with the current fonts on the system (red/white cross). This allows a user to make a sensible selection of a font to use or whether they will have a problem (and a replacement by the replacement character '�') for any symbols. Updates Lua setRoomChar and getRoomChar to handle the wider range of things that can be used. getRoomChar NOW allows for an existing character to be cleared with an empty string or a space as the char attribute. The map format version has been incremented to allow the data needed to be saved directly into the binary file format but failback code is in place that means that this feature can be carried in map and room user data instead for map format versions down to 17 - the current default is 18 and there is limited support to fail gracefully down to the 16 that Mudlet 2.1 uses (all the room letter markings that are not supported will become '?', and the font data will be lost, but the correct room character data will still be in the room user data.) Following review: * I replaced some colour specifications (white and transparent) with Qt constants. * Use the same inline function flushSymbolPixmapCache() to clear the map symbol pixmap cache in all places where it might be useful. * Simplify a couple of places where an if(...) {...} else {...} can be replaced with the (...) ? (...) : (...) operator. * Limit the number of room numbers displayed for each symbol in the new widget - to avoid complications where there are huge numbers of rooms using a symbol. * Replace a use of QTableWidget::clearContents() with QTableWidgets::setRowCount(0) as I was getting some odd, deep in the Qt internal library issues {Fatal Seg. Faults!} with the former, which I suspect, but could not prove, might have been a re-entrancy issue caused by the method containing it being called indirectly by an asynchronous SIGNAL/SLOT originating in the value change from the map symbol font selection QFontComboBox... Revised to NOT do scaling when drawing room symbols from cache: the previous QPainter::drawPixmap(...) performed a scaling operation to make the symbol pixmap fit the specified rectangle. This is the cause behind the poor rendering of text characters as the scaling undoes the benefits of anti-aliasing and takes time to do. This should be faster now because the pixmaps are generated at the size/resolution they are needed (though they do have to be thrown away and regenerated if the zoom or other sizing factors change) - they do however look better to me! Also: * merged (int) TRoom::xzoom and TRoom::yzoom into TRoom::xyzoom. * added the symbol scaling "fudge-factor" to the "Special Options" tab of the "Profile preferences" dialog - it may be helpful to artificially over-size (> 1.00) or under-size (< 1.00) the symbols in some situations. * uses the word symbol rather than just glyph/grapheme in some texts. Also modified 2D mapper "Symbol" tooltip to observe that more than one letter/symbol can be used (although they will be drawn smaller so that they still fit). Add tool-tips to profile preferences dialog for font controls (except for "fudge factor" control (with range x0.50 to x2.00 for scaling of symbol to test rectangle used to fit it into the room shape)... I have consistently mispelled chosen as choosen but I have fixed that now...! Also added tooltips to map glyph usage table/widget. WorkAround: try to force a specific US mirror for zziplib on AppVeyor CI AppVeyor is based in Vancouver, Canada so the nearest SF Mirror is in the US so this commit forces the use of that mirror for that library for the CI build process as an attempt to get around the repeated, intermittent failures to get that library from SourceForge (it is now the only item that needs to be downloaded from there for such builds)... Also adds another CI file that was not mentioned before in the qmake project file and thus did not show up in the Qt IDE. Following extensive discussions it has been made clear that introducing replacements for the lua [gs]etRoomChar(...) is not going to happen. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-03-28 14:06:12 +01:00
fix: profile close during a map operation, Discord presence truncation, and interrupting ttsSpeak() (#9686) #### Brief overview of PR changes/additions - Closing a profile no longer frees the map out from under a running import, export or download. `TMap` counts the operations that pump `qApp->processEvents()`, and `mudlet::closeHost()` - which one of those pumps is what delivers it - stops the operation and destroys the `Host` once it has unwound, instead of half way through it. - Discord presence fields keep their last character and are only ever cut between characters: each buffer is now the documented limit plus room for its terminator, and a new `utils::copyUtf8String()` walks the cut back to a character boundary. - An interrupting `ttsSpeak()` announces the utterance it starts, and the `Ready` an engine reports for the utterance it cut off no longer drains `ttsQueue()` over the top of the one the script asked for. #### Motivation for adding to Mudlet Each is a filed defect, and each was reproduced before it was fixed. The map one is a use-after-free: ASan reports `heap-use-after-free` inside `TMap::readJsonMapFile()`, freed by `~TMap` <- `~Host` <- `HostManager::deleteHost` <- `mudlet::closeHost` delivered by the import's own `processEvents()`. The Discord one is worse than one field looking wrong: a single over-long non-ASCII field makes the whole `SET_ACTIVITY` payload undecodable, so the entire presence update is discarded - the fake Discord client recorded exactly that. The TTS one silently drops speech: `ttsQueue()` plus an interrupting `ttsSpeak()` speaks the queued line and never speaks the requested one. #### Other info (issues closed, discussion etc) Closes #9520, closes #9634, closes #9659. `MapCloseDuringImportTest` stages the close through `mudlet::slot_closeProfileByName()` and lets the map operation's own pump deliver it; the functional tests build with ASan, so the pre-fix run is a sanitizer report rather than an inference. `TtsInterruptingSpeakTest` hands `ttsStateChanged()` the `Ready` a real engine sends, which Qt's mock engine never does - the mock-visible half is pinned in `Media_spec.lua`, where the two specs that recorded the old behaviour are updated. `Discord_spec.lua` gains four end-to-end specs against `CI/discord-ipc-fixture.py` asserting that the captured frame still decodes as JSON and that a field is cut on a character boundary, and `DiscordTest.cpp` covers the same at unit level. Every new or changed test was confirmed to fail without its fix. Two things deliberately left alone, both older than this PR: `Host::requestClose()` still runs nested inside the map operation's pump (it saves the profile there), and an XML import or a map download has no cancel to poll, so a close waits for it rather than stopping it. **Test case:** Export a large map with `exportJsonMap()` and close the profile's tab while it runs; then `setDiscordDetail(string.rep("ä", 65))` and confirm the presence still updates; then `ttsQueue("queued line") ttsSpeak("first")` followed immediately by `ttsSpeak("second")` and confirm "second" is what gets spoken. Assisted-by: Claude:claude-opus-5
2026-08-07 06:10:42 +02:00
void TMap::requestMapOperationAbort()
{
if (!mMapOperationDepth || mMapOperationAbortRequested) {
return;
}
mMapOperationAbortRequested = true;
// Deliberately not slot_mapProgressDialogCancelled(): that is the user
// pressing Abort and says so in the console, whereas this is the profile
// going away and has no console left to say it to. What it does share is
// the flag the JSON import and export poll at their next progress step, and
// dropping a download that would otherwise hold the close up on the network.
mMapProgressCancelRequested = true;
if (mMapProgressIsTransfer && mpNetworkReply) {
mpNetworkReply->abort();
}
}
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
void TMap::slot_mapProgressDialogCancelled()
{
// The JSON path polls mMapProgressCancelRequested in its increment loop; the
// transfer path needs its network reply aborted here.
mMapProgressCancelRequested = true;
if (mMapProgressIsTransfer) {
slot_downloadCancel();
}
}
void TMap::warnIfMapProgressUnwired(const char* context, const bool transferPath)
{
static const QMetaMethod transferStart = QMetaMethod::fromSignal(&TMap::signal_mapTransferProgressStart);
static const QMetaMethod jsonStart = QMetaMethod::fromSignal(&TMap::signal_mapJsonProgressStart);
static const QMetaMethod progressClose = QMetaMethod::fromSignal(&TMap::signal_mapProgressClose);
if (isSignalConnected(transferPath ? transferStart : jsonStart) && isSignalConnected(progressClose)) {
return;
}
qWarning().nospace() << "TMap::" << context
<< "() WARNING - no frontend is connected to show the map progress dialog; the operation will run without a visible progress dialog and cannot be canceled from one.";
}
Enhance: add ability to set any glyph as a room symbol (#1543) This is a squashed down commit containing several commits with messages - this is the edited combination of all the messages: As well as being able to use any grapheme it is possible to use a short word as well as anything printable from any of the Unicode Multiple Planes; although the former will become smaller to fit within both the square and round room shapes on the 2D mapper. Adds controls to the profile preference to set the (preferred) font to use to set the room symbols from and a checkbox to only use that font. Additionally a sub-dialog can be brought up which lists the details of all the different symbols on the map - showing the Unicode codepoint(s) for each and showing how they would be rendered if only the selected font is used and if any font is permitted, along with a count of the usages and the rooms that use each one... A status icon is also displayed showing whether the symbol can be rendered entirely with the selected font (green tick), only by using glyphs from other fonts (yellow ! warning) or not with the current fonts on the system (red/white cross). This allows a user to make a sensible selection of a font to use or whether they will have a problem (and a replacement by the replacement character '�') for any symbols. Updates Lua setRoomChar and getRoomChar to handle the wider range of things that can be used. getRoomChar NOW allows for an existing character to be cleared with an empty string or a space as the char attribute. The map format version has been incremented to allow the data needed to be saved directly into the binary file format but failback code is in place that means that this feature can be carried in map and room user data instead for map format versions down to 17 - the current default is 18 and there is limited support to fail gracefully down to the 16 that Mudlet 2.1 uses (all the room letter markings that are not supported will become '?', and the font data will be lost, but the correct room character data will still be in the room user data.) Following review: * I replaced some colour specifications (white and transparent) with Qt constants. * Use the same inline function flushSymbolPixmapCache() to clear the map symbol pixmap cache in all places where it might be useful. * Simplify a couple of places where an if(...) {...} else {...} can be replaced with the (...) ? (...) : (...) operator. * Limit the number of room numbers displayed for each symbol in the new widget - to avoid complications where there are huge numbers of rooms using a symbol. * Replace a use of QTableWidget::clearContents() with QTableWidgets::setRowCount(0) as I was getting some odd, deep in the Qt internal library issues {Fatal Seg. Faults!} with the former, which I suspect, but could not prove, might have been a re-entrancy issue caused by the method containing it being called indirectly by an asynchronous SIGNAL/SLOT originating in the value change from the map symbol font selection QFontComboBox... Revised to NOT do scaling when drawing room symbols from cache: the previous QPainter::drawPixmap(...) performed a scaling operation to make the symbol pixmap fit the specified rectangle. This is the cause behind the poor rendering of text characters as the scaling undoes the benefits of anti-aliasing and takes time to do. This should be faster now because the pixmaps are generated at the size/resolution they are needed (though they do have to be thrown away and regenerated if the zoom or other sizing factors change) - they do however look better to me! Also: * merged (int) TRoom::xzoom and TRoom::yzoom into TRoom::xyzoom. * added the symbol scaling "fudge-factor" to the "Special Options" tab of the "Profile preferences" dialog - it may be helpful to artificially over-size (> 1.00) or under-size (< 1.00) the symbols in some situations. * uses the word symbol rather than just glyph/grapheme in some texts. Also modified 2D mapper "Symbol" tooltip to observe that more than one letter/symbol can be used (although they will be drawn smaller so that they still fit). Add tool-tips to profile preferences dialog for font controls (except for "fudge factor" control (with range x0.50 to x2.00 for scaling of symbol to test rectangle used to fit it into the room shape)... I have consistently mispelled chosen as choosen but I have fixed that now...! Also added tooltips to map glyph usage table/widget. WorkAround: try to force a specific US mirror for zziplib on AppVeyor CI AppVeyor is based in Vancouver, Canada so the nearest SF Mirror is in the US so this commit forces the use of that mirror for that library for the CI build process as an attempt to get around the repeated, intermittent failures to get that library from SourceForge (it is now the only item that needs to be downloaded from there for such builds)... Also adds another CI file that was not mentioned before in the qmake project file and thus did not show up in the Qt IDE. Following extensive discussions it has been made clear that introducing replacements for the lua [gs]etRoomChar(...) is not going to happen. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
2018-03-28 14:06:12 +01:00
QHash<QString, QSet<int>> TMap::roomSymbolsHash()
{
QHash<QString, QSet<int>> results;
QHashIterator<int, TRoom*> itRoom(mpRoomDB->getRoomMap());
while (itRoom.hasNext()) {
itRoom.next();
if (itRoom.value() && !itRoom.value()->mSymbol.isEmpty()) {
if (results.contains(itRoom.value()->mSymbol)) {
results[itRoom.value()->mSymbol].insert(itRoom.key());
} else {
QSet<int> newEntry;
newEntry << itRoom.key();
results.insert(itRoom.value()->mSymbol, newEntry);
}
}
}
return results;
}
void TMap::setMmpMapLocation(const QString& location)
{
if (mMmpMapLocation == location) {
return;
}
mMmpMapLocation = location;
qDebug() << "MMP map registered at" << mMmpMapLocation;
emit signal_mmpMapLocationChanged();
}
QString TMap::getMmpMapLocation() const
{
return mMmpMapLocation;
}
Roomnames (#3992) * Map: Add an option to show room names below their IDs. This is a fairly straightforward extension. TODO: use a separate font. * basic support for a separate font for room names * Use black room names on light background * Room name display and font sizing fixes Room name display is now independent of room number display. The cut-off for the font size is lower (4 instead of 7). Room names are scaled as if the number 88 would be printed in the room box, which works for all practical purposes. Font size discovery is now done in floating point, and by scaling with factors 1.2 (up) and 1.05 (down) which is faster *and* looks way better. * Don't show room names in grid mode * Tweak font size calculation Ensure that we start with a reasonable font size * Added functions to get/set a room name's offset float x/y, relative to the room rectangle (and in its units). TODO: document in the wiki: getRoomNameOffset(id) setRoomNameOffset(id, x_offset, y_offset) * Save file version updated to 21 Added: * global: room name font + size adjustment * per room: label offset * remove LayoutDirection directives * Re-sorted the grid layout items in ui/profile_prefs * Fix room name placement directly under the room's rectangle, no strange offset * Add userdata flag "room.ui_showName" indicating whether to show room name * Move room label position to userdata * Cleanup The flag whether to display room labels (both globally and per-room) is now stored in userdata. Reverted: ad6d3 Re-sorted the grid layout items in ui/profile_prefs 76834 remove LayoutDirection directives 5d81e Save file version updated to 21 TODO: flipping the global flag crashes for no good reason. * Crash workaround Not inlining "setUserDataBool" triggers a double-free bug (Debian amd64, Qt 5.14.2-3, gcc 10.2.0-9). I'm investigating this; in the meantime, this patch should be an acceptable workaround. * Update src/mudlet-lua/lua/GUIUtils.lua * Appease codefactor * Hide showRoomNames checkbox if no room name infrastructure exists as exhibited by map userData "room.ui_showName" not being present at all Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2020-10-23 14:49:42 +02:00
bool TMap::getRoomNamesPresent()
{
return mUserData.contains(ROOM_UI_SHOWNAME);
}
bool TMap::getRoomNamesShown()
{
return getUserDataBool(mUserData, ROOM_UI_SHOWNAME, false);
}
void TMap::setRoomNamesShown(bool shown)
{
setUserDataBool(mUserData, ROOM_UI_SHOWNAME, shown);
}
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
/*
* Notes on the format version numbers in JSON files - we use this to track any
* changes in a major.minor number format, the minor number is to be three
* digits long.
*
* 0.002 was the first published draft
* 0.003 changed the format to encapsulate the room symbol as an object
* which contains text and a color which was added separately during the
* development of the JSON handling code. Also refactored the storage of
* colors to identify whether there is an alpha component or not in the
* array of values.
* 1.000 is identical to 0.003 - but changed to make sense from a release point
* of view.
*
* Currently only version 1.000 is expected or handled
*/
std::pair<bool, QString> TMap::writeJsonMapFile(const QString& dest)
{
fix: profile close during a map operation, Discord presence truncation, and interrupting ttsSpeak() (#9686) #### Brief overview of PR changes/additions - Closing a profile no longer frees the map out from under a running import, export or download. `TMap` counts the operations that pump `qApp->processEvents()`, and `mudlet::closeHost()` - which one of those pumps is what delivers it - stops the operation and destroys the `Host` once it has unwound, instead of half way through it. - Discord presence fields keep their last character and are only ever cut between characters: each buffer is now the documented limit plus room for its terminator, and a new `utils::copyUtf8String()` walks the cut back to a character boundary. - An interrupting `ttsSpeak()` announces the utterance it starts, and the `Ready` an engine reports for the utterance it cut off no longer drains `ttsQueue()` over the top of the one the script asked for. #### Motivation for adding to Mudlet Each is a filed defect, and each was reproduced before it was fixed. The map one is a use-after-free: ASan reports `heap-use-after-free` inside `TMap::readJsonMapFile()`, freed by `~TMap` <- `~Host` <- `HostManager::deleteHost` <- `mudlet::closeHost` delivered by the import's own `processEvents()`. The Discord one is worse than one field looking wrong: a single over-long non-ASCII field makes the whole `SET_ACTIVITY` payload undecodable, so the entire presence update is discarded - the fake Discord client recorded exactly that. The TTS one silently drops speech: `ttsQueue()` plus an interrupting `ttsSpeak()` speaks the queued line and never speaks the requested one. #### Other info (issues closed, discussion etc) Closes #9520, closes #9634, closes #9659. `MapCloseDuringImportTest` stages the close through `mudlet::slot_closeProfileByName()` and lets the map operation's own pump deliver it; the functional tests build with ASan, so the pre-fix run is a sanitizer report rather than an inference. `TtsInterruptingSpeakTest` hands `ttsStateChanged()` the `Ready` a real engine sends, which Qt's mock engine never does - the mock-visible half is pinned in `Media_spec.lua`, where the two specs that recorded the old behaviour are updated. `Discord_spec.lua` gains four end-to-end specs against `CI/discord-ipc-fixture.py` asserting that the captured frame still decodes as JSON and that a field is cut on a character boundary, and `DiscordTest.cpp` covers the same at unit level. Every new or changed test was confirmed to fail without its fix. Two things deliberately left alone, both older than this PR: `Host::requestClose()` still runs nested inside the map operation's pump (it saves the profile there), and an XML import or a map download has no cancel to poll, so a close waits for it rather than stopping it. **Test case:** Export a large map with `exportJsonMap()` and close the profile's tab while it runs; then `setDiscordDetail(string.rep("ä", 65))` and confirm the presence still updates; then `ttsQueue("queued line") ttsSpeak("first")` followed immediately by `ttsSpeak("second")` and confirm "second" is what gets spoken. Assisted-by: Claude:claude-opus-5
2026-08-07 06:10:42 +02:00
const MapOperationScope operationScope(this);
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
QString destination{dest};
if (destination.isEmpty()) {
const QString destFolder = mudlet::getMudletPath(enums::profileMapsPath, mProfileName);
const QDir destDir(destFolder);
if (!destDir.exists()) {
destDir.mkdir(destFolder);
}
destination = mudlet::getMudletPath(enums::profileDateTimeStampedJsonMapPathFileName, mProfileName, QDateTime::currentDateTime().toString(qsl("yyyy-MM-dd#HH-mm-ss")));
}
if (!destination.endsWith(QLatin1String(".json"), Qt::CaseInsensitive)) {
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
destination.append(QLatin1String(".json"));
}
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
if (mMapProgressStandalone) {
return {false, qsl("import or export already in progress")};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
mProgressDialogRoomsTotal = mpRoomDB->getRoomMap().count();
mProgressDialogAreasTotal = mpRoomDB->getAreaMap().count();
mProgressDialogLabelsTotal = 0;
for (const auto area : mpRoomDB->getAreaMap()) {
if (area) {
mProgressDialogLabelsTotal += area->getPermanentLabelIds().count();
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
}
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
mMapProgressStandalone = true;
mMapProgressIsTransfer = false;
mMapProgressCancelRequested = false;
mMapProgressStandaloneMaximum = static_cast<int>(mProgressDialogRoomsTotal);
warnIfMapProgressUnwired(__func__, false);
//: This is a title of a progress window.
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
emit signal_mapJsonProgressStart(tr("Map JSON export"),
tr("Exporting JSON map data from %1\n"
"Areas: %2 of: %3 Rooms: %4 of: %5 Labels: %6 of: %7...")
.arg(mProfileName,
QLatin1String("0"),
QString::number(mProgressDialogAreasTotal),
QLatin1String("0"),
QString::number(mProgressDialogRoomsTotal),
QLatin1String("0"),
QString::number(mProgressDialogLabelsTotal)),
tr("Abort"),
static_cast<int>(mProgressDialogRoomsTotal));
emit signal_mapProgressSetValue(0);
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
qApp->processEvents();
QSaveFile file(destination);
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
if (!file.open(QFile::OpenMode(QFile::Text | QFile::WriteOnly))) {
qWarning().noquote().nospace() << "TMap::writeJsonMapFile(...) WARNING - Could not open save file \"" << destination << "\".";
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
emit signal_mapProgressClose();
mMapProgressStandalone = false;
return {false, qsl("could not open save file \"%1\", reason: %2").arg(destination.toHtmlEscaped(), file.errorString())};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
QJsonObject mapObj;
mapObj.insert(QLatin1String("formatVersion"), static_cast<double>(1.000));
writeJsonUserData(mapObj);
QList<int> areaRawIdsList{mpRoomDB->getAreaMap().keys()};
QList<int> areaNameRawIdsList{mpRoomDB->getAreaNamesMap().keys()};
QSet<int> areaIdsSet{areaRawIdsList.begin(), areaRawIdsList.end()};
areaIdsSet.unite(QSet<int>{areaNameRawIdsList.begin(), areaNameRawIdsList.end()});
QList<int> areaIdsList{areaIdsSet.begin(), areaIdsSet.end()};
if (areaIdsList.count() > 1) {
std::sort(areaIdsList.begin(), areaIdsList.end());
}
mProgressDialogAreasCount = 0;
mProgressDialogRoomsCount = 0;
mProgressDialogLabelsCount = 0;
bool abort = false;
QJsonArray areasArray;
for (const auto area : mpRoomDB->getAreaMap()) {
if (area) {
area->writeJsonArea(areasArray);
}
++mProgressDialogAreasCount;
if (incrementJsonProgressDialog(true, true, 0)) {
abort = true;
break;
}
}
if (abort) {
file.cancelWriting();
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
emit signal_mapProgressClose();
mMapProgressStandalone = false;
return {false, qsl("aborted by user")};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
const QJsonValue areasValue{areasArray};
mapObj.insert(QLatin1String("areas"), areasValue);
// Should Qt change things so that the order in the file is not
// alphabetically sorted but instead dependent on actually insertion order
// then these must be precalculated and put first - as they are needed to
// drive the progress dialogue:
mapObj.insert(QLatin1String("areaCount"), static_cast<double>(areaIdsList.count()));
mapObj.insert(QLatin1String("roomCount"), static_cast<double>(mProgressDialogRoomsCount));
mapObj.insert(QLatin1String("labelCount"), static_cast<double>(mProgressDialogLabelsTotal));
const QJsonValue defaultAreaNameValue{mDefaultAreaName};
mapObj.insert(QLatin1String("defaultAreaName"), defaultAreaNameValue);
const QJsonValue anonymousAreaNameValue{mUnnamedAreaName};
mapObj.insert(QLatin1String("anonymousAreaName"), anonymousAreaNameValue);
if (!mEnvColors.isEmpty()) {
QJsonObject envColorObj;
QMapIterator<int, int> itEnvColor(mEnvColors);
while (itEnvColor.hasNext()) {
itEnvColor.next();
envColorObj.insert(QString::number(itEnvColor.key()), static_cast<double>(itEnvColor.value()));
}
const QJsonValue mEnvColorsValue{envColorObj};
mapObj.insert(QLatin1String("envToColorMapping"), mEnvColorsValue);
}
QJsonObject playerRoomIdHashObj;
QHashIterator<QString, int> itplayerRoomIdHash(mRoomIdHash);
while (itplayerRoomIdHash.hasNext()) {
itplayerRoomIdHash.next();
playerRoomIdHashObj.insert(itplayerRoomIdHash.key(), static_cast<double>(itplayerRoomIdHash.value()));
}
const QJsonValue playerRoomIdHashsValue{playerRoomIdHashObj};
mapObj.insert(QLatin1String("playersRoomId"), playerRoomIdHashsValue);
QJsonArray customEnvColorArray;
QMapIterator<int, QColor> itCustomEnvColor(mCustomEnvColors);
while (itCustomEnvColor.hasNext()) {
itCustomEnvColor.next();
QJsonObject customEnvColorObj{};
// Should insert an array value into the customEnvColorObj with the key
// "colorRGBA"
writeJsonColor(customEnvColorObj, itCustomEnvColor.value());
customEnvColorObj.insert(QLatin1String("id"), QJsonValue{itCustomEnvColor.key()});
2021-08-22 08:01:05 +02:00
// Convert the customEnvColorObj into a QJsonValue:
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
const QJsonValue customEnvColorValue{customEnvColorObj};
// Now append this object onto the array:
customEnvColorArray.append(customEnvColorValue);
}
// Convert the array of all the mCustomEnvColors into a QJsonValue so we
// can add it to the map object:
const QJsonValue mCustomEnvColorsValue{customEnvColorArray};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
mapObj.insert(QLatin1String("customEnvColors"), mCustomEnvColorsValue);
mapObj.insert(QLatin1String("mapSymbolFontDetails"), mMapSymbolFont.toString());
mapObj.insert(QLatin1String("mapSymbolFontFudgeFactor"), static_cast<double>(mMapSymbolFontFudgeFactor));
mapObj.insert(QLatin1String("onlyMapSymbolFontToBeUsed"), mIsOnlyMapSymbolFontToBeUsed);
QJsonArray playerRoomColorsArray;
QJsonObject playerRoomOuterColorObj;
QJsonObject playerRoomInnerColorObj;
writeJsonColor(playerRoomOuterColorObj, mPlayerRoomOuterColor);
writeJsonColor(playerRoomInnerColorObj, mPlayerRoomInnerColor);
const QJsonValue playerRoomOuterColorValue{playerRoomOuterColorObj};
const QJsonValue playerRoomInnerColorValue{playerRoomInnerColorObj};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
playerRoomColorsArray.append(playerRoomOuterColorValue);
playerRoomColorsArray.append(playerRoomInnerColorValue);
const QJsonValue playerRoomColorsValue{playerRoomColorsArray};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
mapObj.insert(QLatin1String("playerRoomColors"), playerRoomColorsValue);
mapObj.insert(QLatin1String("playerRoomStyle"), static_cast<double>(mPlayerRoomStyle));
mapObj.insert(QLatin1String("playerRoomOuterDiameterPercentage"), static_cast<double>(mPlayerRoomOuterDiameterPercentage));
mapObj.insert(QLatin1String("playerRoomInnerDiameterPercentage"), static_cast<double>(mPlayerRoomInnerDiameterPercentage));
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
emit signal_mapProgressSetLabel(tr("Exporting JSON map file from %1 - writing data to file:\n"
"%2 ...")
.arg(mProfileName, destination));
emit signal_mapProgressSetValue(0);
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
// Hide the cancel button as we can't stop now:
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
emit signal_mapProgressDisableCancel();
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
file.write(QJsonDocument(mapObj).toJson(QJsonDocument::Indented));
if (!file.commit()) {
qDebug() << "TMap::writeJsonMapFile: error saving JSON map: " << file.errorString();
}
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
emit signal_mapProgressClose();
mMapProgressStandalone = false;
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
return {file.error() == QFileDevice::NoError, ((file.error() == QFileDevice::NoError) ? QString() : qsl("could not export file, reason: %1").arg(file.errorString()))};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
2021-04-02 19:10:16 +01:00
// The translatable messages are used within this file and do not need to
// mention the file concerned whereas the untranslated messages are used by the
// Lua sub-system and do need to report the file:
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
std::pair<bool, QString> TMap::readJsonMapFile(const QString& source, const bool translatableTexts)
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
{
fix: profile close during a map operation, Discord presence truncation, and interrupting ttsSpeak() (#9686) #### Brief overview of PR changes/additions - Closing a profile no longer frees the map out from under a running import, export or download. `TMap` counts the operations that pump `qApp->processEvents()`, and `mudlet::closeHost()` - which one of those pumps is what delivers it - stops the operation and destroys the `Host` once it has unwound, instead of half way through it. - Discord presence fields keep their last character and are only ever cut between characters: each buffer is now the documented limit plus room for its terminator, and a new `utils::copyUtf8String()` walks the cut back to a character boundary. - An interrupting `ttsSpeak()` announces the utterance it starts, and the `Ready` an engine reports for the utterance it cut off no longer drains `ttsQueue()` over the top of the one the script asked for. #### Motivation for adding to Mudlet Each is a filed defect, and each was reproduced before it was fixed. The map one is a use-after-free: ASan reports `heap-use-after-free` inside `TMap::readJsonMapFile()`, freed by `~TMap` <- `~Host` <- `HostManager::deleteHost` <- `mudlet::closeHost` delivered by the import's own `processEvents()`. The Discord one is worse than one field looking wrong: a single over-long non-ASCII field makes the whole `SET_ACTIVITY` payload undecodable, so the entire presence update is discarded - the fake Discord client recorded exactly that. The TTS one silently drops speech: `ttsQueue()` plus an interrupting `ttsSpeak()` speaks the queued line and never speaks the requested one. #### Other info (issues closed, discussion etc) Closes #9520, closes #9634, closes #9659. `MapCloseDuringImportTest` stages the close through `mudlet::slot_closeProfileByName()` and lets the map operation's own pump deliver it; the functional tests build with ASan, so the pre-fix run is a sanitizer report rather than an inference. `TtsInterruptingSpeakTest` hands `ttsStateChanged()` the `Ready` a real engine sends, which Qt's mock engine never does - the mock-visible half is pinned in `Media_spec.lua`, where the two specs that recorded the old behaviour are updated. `Discord_spec.lua` gains four end-to-end specs against `CI/discord-ipc-fixture.py` asserting that the captured frame still decodes as JSON and that a field is cut on a character boundary, and `DiscordTest.cpp` covers the same at unit level. Every new or changed test was confirmed to fail without its fix. Two things deliberately left alone, both older than this PR: `Host::requestClose()` still runs nested inside the map operation's pump (it saves the profile there), and an XML import or a map download has no cancel to poll, so a close waits for it rather than stopping it. **Test case:** Export a large map with `exportJsonMap()` and close the profile's tab while it runs; then `setDiscordDetail(string.rep("ä", 65))` and confirm the presence still updates; then `ttsQueue("queued line") ttsSpeak("first")` followed immediately by `ttsSpeak("second")` and confirm "second" is what gets spoken. Assisted-by: Claude:claude-opus-5
2026-08-07 06:10:42 +02:00
const MapOperationScope operationScope(this);
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
const QString oldDefaultAreaName{mDefaultAreaName};
const QString oldUnnamedName{mUnnamedAreaName};
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
if (mMapProgressStandalone) {
return {false, (translatableTexts ? tr("import or export already in progress") : qsl("import or export already in progress"))};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
QFile file(source);
if (!file.open(QFile::ReadOnly)) {
qWarning().noquote().nospace() << "TMap::readJsonMapFile(...) WARNING - Could not open JSON file \"" << source << "\".";
return {false, (translatableTexts ? tr("could not open file") : qsl("could not open file \"%1\"").arg(source))};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
const QByteArray mapData = file.readAll();
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
file.close();
QJsonParseError jsonErr;
const QJsonDocument doc(QJsonDocument::fromJson(mapData, &jsonErr));
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
if (jsonErr.error != QJsonParseError::NoError) {
2021-04-02 19:10:16 +01:00
return {false,
(translatableTexts ? tr("could not parse file, reason: \"%1\" at offset %2").arg(jsonErr.errorString(), QString::number(jsonErr.offset))
: qsl("could not parse file \"%1\", reason: \"%2\" at offset %3").arg(source, jsonErr.errorString(), QString::number(jsonErr.offset)))};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
if (doc.isEmpty()) {
qDebug().nospace().noquote() << "TMap::readJsonMapFile(\"" << source << "\") INFO - no Json file data detected, this is not a Mudlet JSON map file.";
return {false, (translatableTexts ? tr("empty Json file, no map data detected") : qsl("empty Json file, no map data detected"))};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
// Read all the base level stuff:
QJsonObject mapObj{doc.object()};
double formatVersion = 0.0f;
if (mapObj.contains(QLatin1String("formatVersion")) && mapObj[QLatin1String("formatVersion")].isDouble()) {
formatVersion = mapObj[QLatin1String("formatVersion")].toDouble();
if (qFuzzyCompare(1.0, formatVersion + 1.0) || formatVersion < 1.0000 || formatVersion > 1.0000) {
// We only handle 1.000f right now (0.001f was borked, 0.002f
// didn't include room symbol color, 0.003 is the same as 1.000
// but the numbered was changed for release into the wild):
qDebug().nospace().noquote() << "TMap::readJsonMapFile(\"" << source << "\") INFO - Version information \"" << formatVersion << "\" was found, and it is not okay.";
2021-04-02 19:10:16 +01:00
return {false,
(translatableTexts ? tr("invalid format version \"%1\" detected").arg(formatVersion, 0, 'f', 3, QLatin1Char('0'))
: qsl("invalid format version \"%1\" detected").arg(formatVersion, 0, 'f', 3, QLatin1Char('0')))};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
} else {
qDebug().nospace().noquote() << "TMap::readJsonMapFile(\"" << source << "\") INFO - Version information was not found. This is not likely to be a Mudlet JSON map file.";
return {false, (translatableTexts ? tr("no format version detected") : qsl("no format version detected"))};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
if (!mapObj.contains(QLatin1String("areas")) || !mapObj.value(QLatin1String("areas")).isArray()) {
2021-04-02 19:10:16 +01:00
return {false, (translatableTexts ? tr("no areas detected") : qsl("no areas detected"))};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
mProgressDialogAreasTotal = qRound(mapObj[QLatin1String("areaCount")].toDouble());
mProgressDialogAreasCount = 0;
mProgressDialogRoomsTotal = qRound(mapObj[QLatin1String("roomCount")].toDouble());
mProgressDialogRoomsCount = 0;
mProgressDialogLabelsTotal = qRound(mapObj[QLatin1String("labelCount")].toDouble());
mProgressDialogLabelsCount = 0;
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
mMapProgressStandalone = true;
mMapProgressIsTransfer = false;
mMapProgressCancelRequested = false;
mMapProgressStandaloneMaximum = static_cast<int>(mProgressDialogRoomsTotal);
warnIfMapProgressUnwired(__func__, false);
//: This is a title of a progress window.
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
emit signal_mapJsonProgressStart(tr("Map JSON import"),
tr("Importing JSON map data to %1\n"
"Areas: %2 of: %3 Rooms: %4 of: %5 Labels: %6 of: %7...")
.arg(mProfileName,
QLatin1String("0"),
QString::number(mProgressDialogAreasTotal),
QLatin1String("0"),
QString::number(mProgressDialogRoomsTotal),
QLatin1String("0"),
QString::number(mProgressDialogLabelsTotal)),
tr("Abort"),
static_cast<int>(mProgressDialogRoomsTotal));
emit signal_mapProgressSetValue(0);
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
qApp->processEvents();
mDefaultAreaName = mapObj[QLatin1String("defaultAreaName")].toString();
mUnnamedAreaName = mapObj[QLatin1String("anonymousAreaName")].toString();
if (mapObj.contains(QLatin1String("userData"))) {
readJsonUserData(mapObj[QLatin1String("userData")].toObject());
}
const QString mapSymbolFontText = mapObj[QLatin1String("mapSymbolFontDetails")].toString();
const float mapSymbolFontFudgeFactor = (qRound(mapObj[QLatin1String("mapSymbolFontFudgeFactor")].toDouble() * 1000.0)) / 1000;
const bool isOnlyMapSymbolFontToBeUsed = mapObj[QLatin1String("onlyMapSymbolFontToBeUsed")].toBool();
const int playerRoomStyle = qRound(mapObj[QLatin1String("playerRoomStyle")].toDouble());
quint8 const playerRoomOuterDiameterPercentage = qRound(mapObj[QLatin1String("playerRoomOuterDiameterPercentage")].toDouble());
quint8 const playerRoomInnerDiameterPercentage = qRound(mapObj[QLatin1String("playerRoomInnerDiameterPercentage")].toDouble());
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
QColor playerRoomOuterColor;
QColor playerRoomInnerColor;
if (mapObj.contains(QLatin1String("playerRoomColors")) && mapObj.value(QLatin1String("playerRoomColors")).isArray()) {
const QJsonArray playerRoomColorArray = mapObj.value(QLatin1String("playerRoomColors")).toArray();
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
if (playerRoomColorArray.size() == 2 && playerRoomColorArray.at(0).isObject() && playerRoomColorArray.at(1).isObject()) {
playerRoomOuterColor = readJsonColor(playerRoomColorArray.at(0).toObject());
playerRoomInnerColor = readJsonColor(playerRoomColorArray.at(1).toObject());
}
}
QMap<int, int> envColors;
if (mapObj.contains(QLatin1String("envToColorMapping")) && mapObj.value(QLatin1String("envToColorMapping")).isObject()) {
const QJsonObject envColorObj{mapObj.value(QLatin1String("envToColorMapping")).toObject()};
if (!envColorObj.isEmpty()) {
for (auto& key : envColorObj.keys()) {
bool isOk = false;
const int index = key.toInt(&isOk);
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
if (isOk && envColorObj.value(key).isDouble()) {
const int value = envColorObj.value(key).toInt();
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
envColors.insert(index, value);
}
}
}
}
QMap<int, QColor> customEnvColors;
if (mapObj.contains(QLatin1String("customEnvColors")) && mapObj.value(QLatin1String("customEnvColors")).isArray()) {
const QJsonArray customEnvColorArray = mapObj.value(QLatin1String("customEnvColors")).toArray();
if (!customEnvColorArray.isEmpty()) {
Fix: correct warnings/errors found whilst working on Windows CI (#7224) #### Brief overview of PR changes/additions Whilst working on getting the Windows CI process to run in a MSYS2+Mingw-w64 environment on AppVeyor in both Qt 5 and 6 and both 32-bits and 64-bits (Qt6 only supports 64-Bit builds). I ran into a number of warnings, some of them about things deprecated in Qt 6.0 or later. This PR should eliminate all of them for our code (though there are a couple in upstream things). #### Motivation for adding to Mudlet Make the build process cleaner all around, especially with moving forward to Qt 6. #### Other info (issues closed, discussion etc) The use of `std::as_const(...)` requires C++17 but we have already mandated that. `qAsConst(...)` is deprecated in Qt 6. Some of the places where the above was being done also were missing the use of a `const` reference rather than the making of a constant copy of the iterated values; these have been fixed as well. A couple of Mudlet classes that I haven't yet cleaned up to move as much of the class initialisation to the header as possible were reporting initialisation ordering issue (`Host` and `TTimer`). I have fixed those but only in the region of the issues, more work there is desirable to clean up every remaining class - but I'm not allowed to leave "TODO:" comments around nowadays! :grinning: `(void) zip_error_to_str(char*, size_t, int, int))` has been obsoleted for a long time now, and I've finally put in something in a couple of places that will use the recommended replacement `(zip_error_t*) zip_get_error(zip*)` and dump the error message out to the OS console - which was not happening in the past. `(QString) QString::fromUtf16(...)` has been obsoleted and alternatives are suggested within the Qt documentation. I've used `QString::fromWCharArray(...)`. Whilst this compiles ***I am not 100% sure I have this correct and a second opinion on this change in `./src/mudlet.cpp` is desirable!*** Qt is renaming in Qt6 a few methods that otherwise function as before: * `(Qt::KeyboardModifiers) QDragEnterEvent::keyboardModifiers()` ==> `QDragEnterEvent::modifiers()` * `(Qt::KeyboardModifiers) QDragMoveEvent::keyboardModifiers()` ==> `QDragMoveEvent::modifiers()` * `(bool) QColor::isValidColor(const QString&)` ==> `(bool) QColor::isValidColorName(QAnyStringView)` * `(void) QColor::setNamedColor(const QString&)` ==> `(QColor) QColor::fromString(QAnyStringView)` * `(QString) QLocale::countryToString(Country)` ==> `(QString) QLocale::territoryToString(Territory)` Windows NTFS permissions checking was being done with a really low-level procedure which has been deprecated in Qt 6.6 and replaced with a slightly better (but also low-level) pair of functions: * `(bool) qEnableNtfsPermissionChecks()` * `(bool) qEnableNtfsPermissionChecks()` to do the same thing in almost the same way with a lesser risk of a "race-condition". There is a higher-level procedure involving the use of a new class `QNtfsPermissionCheckGuard` but that is a different way of doing things that is not a drop-in replacement AFAICT. There was an unhandled `case` (for `QTextToSpeech::State::Synthesizing`) in `(void) TLuaInterpreter::ttsStateChanged(QTextToSpeech::State)` - I've put in something to report that state but it is not clear that this, seemingly, transient state, needs anything extra than that. For instance, given that it looks to be associated with preparing a text to be spoken it might be reasonable to report the text involved as the `Speaking` state does... The point at which it was introduced is also unclear as that isn't documented! Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@hey.com>
2024-05-20 19:00:51 +00:00
for (const auto& customEnvColorValue : std::as_const(customEnvColorArray)) {
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
const QJsonObject customEnvColorObj{customEnvColorValue.toObject()};
if (customEnvColorObj.contains(QLatin1String("id"))
&& ((customEnvColorObj.contains(QLatin1String("color32RGBA")) && customEnvColorObj.value(QLatin1String("color32RGBA")).isArray())
|| (customEnvColorObj.contains(QLatin1String("color24RGB")) && customEnvColorObj.value(QLatin1String("color24RGB")).isArray()))
&& customEnvColorObj.value(QLatin1String("id")).isDouble()) {
const int id{customEnvColorObj.value(QLatin1String("id")).toInt()};
const QColor color{readJsonColor(customEnvColorObj)};
customEnvColors.insert(id, color);
}
}
}
}
QHash<QString, int> playersRoomId;
if (mapObj.contains(QLatin1String("playersRoomId")) && mapObj.value(QLatin1String("playersRoomId")).isObject()) {
const QJsonObject playersRoomIdObj{mapObj.value(QLatin1String("playersRoomId")).toObject()};
if (!playersRoomIdObj.isEmpty()) {
for (auto& profileName : playersRoomIdObj.keys()) {
if (playersRoomIdObj.value(profileName).isDouble()) {
playersRoomId.insert(profileName, playersRoomIdObj.value(profileName).toInt());
}
}
}
}
improve: improve memory safety by using smart pointers (#9239) ### Refactor: replace raw pointer ownership with smart pointers across core subsystems #### Brief overview of PR changes/additions Replaces raw pointer ownership patterns with `std::unique_ptr` and `std::map` across several core subsystems: - **Host**: `mStopWatchMap` (`QMap<int, stopWatch*>` → `std::map<int, unique_ptr<stopWatch>>`), `profileShortcuts` (`QMap<QString, QKeySequence*>` → `std::map<QString, unique_ptr<QKeySequence>>`). Removes `qDeleteAll` in destructor and `delete mMMCPServer`. - **TMap**: `mpRoomDB` raw pointer → `unique_ptr` - **VarUnit**: `base` raw pointer → `unique_ptr` - **TTrigger**: condition map storage converted to `unique_ptr`, destructor simplified - **discord**: handler and presence maps converted from raw pointer `QMap` to `unique_ptr` + `std::map` - **Updater**: `mFeed` and `mUpdateDialog` converted to `unique_ptr` #### Motivation for adding to Mudlet These patterns were identified as sources of memory leaks and potential use-after-free bugs. Using smart pointers makes ownership explicit, eliminates manual cleanup code, and ensures correct destruction even on early-exit paths. #### Other info (issues closed, discussion etc) sorry this one is still pretty big, but most of the changes are the same for each thing so reviewing them together probably makes sense. sadly there isn't much to see here other than no slow uptick of heap size :-[ Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:42:09 +12:00
auto pNewRoomDB = std::make_unique<TRoomDB>(this);
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
bool abort = false;
for (int i = 0, total = mapObj.value(QLatin1String("areas")).toArray().count(); i < total; ++i) {
improve: improve memory safety by using smart pointers (#9239) ### Refactor: replace raw pointer ownership with smart pointers across core subsystems #### Brief overview of PR changes/additions Replaces raw pointer ownership patterns with `std::unique_ptr` and `std::map` across several core subsystems: - **Host**: `mStopWatchMap` (`QMap<int, stopWatch*>` → `std::map<int, unique_ptr<stopWatch>>`), `profileShortcuts` (`QMap<QString, QKeySequence*>` → `std::map<QString, unique_ptr<QKeySequence>>`). Removes `qDeleteAll` in destructor and `delete mMMCPServer`. - **TMap**: `mpRoomDB` raw pointer → `unique_ptr` - **VarUnit**: `base` raw pointer → `unique_ptr` - **TTrigger**: condition map storage converted to `unique_ptr`, destructor simplified - **discord**: handler and presence maps converted from raw pointer `QMap` to `unique_ptr` + `std::map` - **Updater**: `mFeed` and `mUpdateDialog` converted to `unique_ptr` #### Motivation for adding to Mudlet These patterns were identified as sources of memory leaks and potential use-after-free bugs. Using smart pointers makes ownership explicit, eliminates manual cleanup code, and ensures correct destruction even on early-exit paths. #### Other info (issues closed, discussion etc) sorry this one is still pretty big, but most of the changes are the same for each thing so reviewing them together probably makes sense. sadly there isn't much to see here other than no slow uptick of heap size :-[ Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:42:09 +12:00
std::unique_ptr<TArea> pArea = std::make_unique<TArea>(this, pNewRoomDB.get());
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
auto [id, name] = pArea->readJsonArea(mapObj.value(QLatin1String("areas")).toArray(), i);
++mProgressDialogAreasCount;
if (incrementJsonProgressDialog(false, true, 0)) {
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
abort = true;
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
break;
}
// This will populate the TRoomDB::areas and TRoomDB::areaNameMap:
pNewRoomDB->addArea(pArea.release(), id, name);
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
if (abort) {
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
emit signal_mapProgressClose();
mMapProgressStandalone = false;
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
mDefaultAreaName = oldDefaultAreaName;
mUnnamedAreaName = oldUnnamedName;
2021-04-02 19:10:16 +01:00
return {false, (translatableTexts ? tr("aborted by user") : qsl("aborted by user"))};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
mCustomEnvColors.swap(customEnvColors);
mEnvColors.swap(envColors);
mIsOnlyMapSymbolFontToBeUsed = isOnlyMapSymbolFontToBeUsed;
QFont mapSymbolFont;
mapSymbolFont.fromString(mapSymbolFontText);
mapSymbolFont.setStyleStrategy(static_cast<QFont::StyleStrategy>((isOnlyMapSymbolFontToBeUsed ? QFont::NoFontMerging : 0) | QFont::PreferOutline | QFont::PreferAntialias | QFont::PreferQuality
| QFont::PreferNoShaping));
mMapSymbolFont.swap(mapSymbolFont);
mMapSymbolFontFudgeFactor = mapSymbolFontFudgeFactor;
mPlayerRoomInnerColor = playerRoomInnerColor;
mPlayerRoomInnerDiameterPercentage = playerRoomInnerDiameterPercentage;
mPlayerRoomOuterColor = playerRoomOuterColor;
mPlayerRoomOuterDiameterPercentage = playerRoomOuterDiameterPercentage;
mPlayerRoomStyle = playerRoomStyle;
mRoomIdHash = playersRoomId;
qDebug().nospace().noquote() << "TMap::readJsonMapFile(...) INFO - parsed a file (version: " << formatVersion << ") containing " << mProgressDialogRoomsCount << " rooms.";
// This is it - the point at which the new map gets activated:
improve: improve memory safety by using smart pointers (#9239) ### Refactor: replace raw pointer ownership with smart pointers across core subsystems #### Brief overview of PR changes/additions Replaces raw pointer ownership patterns with `std::unique_ptr` and `std::map` across several core subsystems: - **Host**: `mStopWatchMap` (`QMap<int, stopWatch*>` → `std::map<int, unique_ptr<stopWatch>>`), `profileShortcuts` (`QMap<QString, QKeySequence*>` → `std::map<QString, unique_ptr<QKeySequence>>`). Removes `qDeleteAll` in destructor and `delete mMMCPServer`. - **TMap**: `mpRoomDB` raw pointer → `unique_ptr` - **VarUnit**: `base` raw pointer → `unique_ptr` - **TTrigger**: condition map storage converted to `unique_ptr`, destructor simplified - **discord**: handler and presence maps converted from raw pointer `QMap` to `unique_ptr` + `std::map` - **Updater**: `mFeed` and `mUpdateDialog` converted to `unique_ptr` #### Motivation for adding to Mudlet These patterns were identified as sources of memory leaks and potential use-after-free bugs. Using smart pointers makes ownership explicit, eliminates manual cleanup code, and ensures correct destruction even on early-exit paths. #### Other info (issues closed, discussion etc) sorry this one is still pretty big, but most of the changes are the same for each thing so reviewing them together probably makes sense. sadly there isn't much to see here other than no slow uptick of heap size :-[ Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 16:42:09 +12:00
mpRoomDB = std::move(pNewRoomDB);
// Need to update the master copy of these details in the Host class:
mpHost->setPlayerRoomStyleDetails(mPlayerRoomStyle, mPlayerRoomOuterDiameterPercentage, mPlayerRoomInnerDiameterPercentage, mPlayerRoomOuterColor, mPlayerRoomInnerColor);
// And redraw the indicator if a 2D map is being shown:
if (mpMapper && mpMapper->mp2dMap) {
mpMapper->mp2dMap->setPlayerRoomStyle(mPlayerRoomStyle);
}
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
emit signal_mapProgressClose();
mMapProgressStandalone = false;
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
return {true, QString()};
}
void TMap::writeJsonUserData(QJsonObject& obj) const
{
QJsonObject userDataObj;
if (mUserData.isEmpty()) {
// Skip creating a user data array if it will be empty:
return;
}
QMapIterator<QString, QString> itDataItem(mUserData);
while (itDataItem.hasNext()) {
itDataItem.next();
const QJsonValue jsonValue{itDataItem.value()};
userDataObj.insert(itDataItem.key(), jsonValue);
}
const QJsonValue jsonValue{userDataObj};
obj.insert(QLatin1String("userData"), jsonValue);
}
// Takes a userData object and parses all its elements
void TMap::readJsonUserData(const QJsonObject& obj)
{
if (obj.isEmpty()) {
// Skip doing anything more if there is nothing to do:
return;
}
for (auto& key : obj.keys()) {
if (obj.value(key).isString()) {
mUserData.insert(key, obj.value(key).toString());
}
}
}
// Inserts a color as an array of 3 or 4 ints (cast to doubles) into the
// supplied object.
void TMap::writeJsonColor(QJsonObject& obj, const QColor& color)
{
QJsonArray colorRGBAArray;
colorRGBAArray.append(static_cast<double>(color.red()));
colorRGBAArray.append(static_cast<double>(color.green()));
colorRGBAArray.append(static_cast<double>(color.blue()));
if (color.alpha() < 255) {
colorRGBAArray.append(static_cast<double>(color.alpha()));
const QJsonValue colorRGBAValue{colorRGBAArray};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
obj.insert(QLatin1String("color32RGBA"), colorRGBAValue);
} else {
const QJsonValue colorRGBAValue{colorRGBAArray};
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
obj.insert(QLatin1String("color24RGB"), colorRGBAValue);
}
}
QColor TMap::readJsonColor(const QJsonObject& obj)
{
if (!((obj.contains(QLatin1String("color32RGBA")) && obj.value(QLatin1String("color32RGBA")).isArray())
|| (obj.contains(QLatin1String("color24RGB")) && obj.value(QLatin1String("color24RGB")).isArray()))) {
// Return a null color if one was not found
return QColor();
}
QJsonArray colorRGBAArray;
bool hasAlpha = false;
int red = 0;
int green = 0;
int blue = 0;
int alpha = 255;
if (obj.contains(QLatin1String("color32RGBA"))) {
colorRGBAArray = obj.value(QLatin1String("color32RGBA")).toArray();
hasAlpha = true;
} else {
colorRGBAArray = obj.value(QLatin1String("color24RGB")).toArray();
}
const int size = colorRGBAArray.size();
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
if ((size == 3 || size == 4) && colorRGBAArray.at(0).isDouble() && colorRGBAArray.at(1).isDouble() && colorRGBAArray.at(2).isDouble()) {
red = qRound(colorRGBAArray.at(0).toDouble());
green = qRound(colorRGBAArray.at(1).toDouble());
blue = qRound(colorRGBAArray.at(2).toDouble());
return QColor(red, green, blue);
}
if (hasAlpha && size == 4 && colorRGBAArray.at(3).isDouble()) {
alpha = qRound(colorRGBAArray.at(3).toDouble());
return QColor(red, green, blue, alpha);
}
return QColor();
}
bool TMap::incrementJsonProgressDialog(const bool isExportNotImport, const bool isRoomNotLabel, const int increment)
{
if (isRoomNotLabel) {
mProgressDialogRoomsCount += increment;
} else {
mProgressDialogLabelsCount += increment;
}
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
emit signal_mapProgressSetValue(static_cast<int>(mProgressDialogRoomsCount));
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
if (isExportNotImport) {
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
emit signal_mapProgressSetLabel(tr("Exporting JSON map data from %1\n"
"Areas: %2 of: %3 Rooms: %4 of: %5 Labels: %6 of: %7...")
.arg(mProfileName,
QString::number(mProgressDialogAreasCount),
QString::number(mProgressDialogAreasTotal),
QString::number(mProgressDialogRoomsCount),
QString::number(mProgressDialogRoomsTotal),
QString::number(mProgressDialogLabelsCount),
QString::number(mProgressDialogLabelsTotal)));
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
} else {
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
emit signal_mapProgressSetLabel(tr("Importing JSON map data to %1\n"
"Areas: %2 of: %3 Rooms: %4 of: %5 Labels: %6 of: %7...")
.arg(mProfileName,
QString::number(mProgressDialogAreasCount),
QString::number(mProgressDialogAreasTotal),
QString::number(mProgressDialogRoomsCount),
QString::number(mProgressDialogRoomsTotal),
QString::number(mProgressDialogLabelsCount),
QString::number(mProgressDialogLabelsTotal)));
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
qApp->processEvents();
infrastructure: decouple the mapper engine from UI dialogs (#9513) #### Brief overview of PR changes/additions - Removes all raw Qt Widgets usage from the map engine: `TMap.{h,cpp}` no longer owns a `QProgressDialog` (and drops a dead `QFileDialog` include), and `XMLimport.{h,cpp}` no longer pulls in `QApplication` (the clipboard read now uses `QGuiApplication::clipboard()`, which lives in Qt Gui). - The standalone map-progress dialog (shown when the mapper is not visible, for map download / XML import and JSON export/import) is now driven by Qt signals carrying pre-translated payloads; the frontend (`TMainConsole`) owns the actual `QProgressDialog`, and a user cancel returns to the engine through `TMap::slot_mapProgressDialogCancelled()`. - Adds `MapProgressDialogSeamTest` covering the transfer-progress state machine, a JSON export/import round trip driving the new signals, a mid-import cancel delivered through the seam (the highest-risk change, since the JSON reader used to poll `QProgressDialog::wasCanceled()` synchronously), and an XML map import re-entered from inside a running JSON operation. #### Motivation for adding to Mudlet Second concrete step of the re-scoped libmudlet plan (a Qt-Widgets-free `mudlet_core` for headless use, testability and WASM). It copies the seam template established in #9507: core emits a pre-translated payload -> frontend owns the widget -> a callback slot returns the answer. The Qt Widgets dependency audit (`cmake/audit-core-widgets.sh`) drops from **151 to 147** offending files; `TMap.cpp`, `TMap.h`, `XMLimport.cpp` and `XMLimport.h` are all now clean. The mapper-owned inline progress path (`dlgMapper`/`T2DMap`, Mudlet's own widgets) is deliberately untouched here - those move wholesale in the later target-split phase. #### Other info (issues closed, discussion etc) Part of #8681 / #9011. Existing translations are unaffected: every progress string keeps its `TMap` `tr()` context, so current translations carry straight over. Two new strings do arrive, both with `//:` translator comments - the warnings shown when a map download or an XML map import is refused because a JSON import/export is already running. The JSON dialog stays non-modal and the download/import dialog keeps its modeless styling, each applied by the frontend. The engine keeps its own `mMapProgressStandalone` / `mMapProgressCancelRequested` / `mMapProgressStandaloneMaximum` state to replace the widget read-backs it used to do (`!= nullptr`, `wasCanceled()`, `maximum()`). If a map operation ever reaches the engine before a console is wired (checked via `isSignalConnected`), `TMap::warnIfMapProgressUnwired()` logs a loud `qWarning` rather than silently running with no progress UI. It also closes a latent null-dereference that exists on `development` today. With the mapper visible a map download takes the inline-progress path, leaving `mpProgressDialog` null - so a JSON export started meanwhile sails past the `if (mpProgressDialog)` "already in progress" check and creates a dialog of its own. When the download then finishes inside the `processEvents()` pump the export is running, `clearTransferProgress()` deletes and nulls *that* dialog, and the export's next `incrementJsonProgressDialog()` dereferences null. The engine now records whose dialog is up (`mMapProgressIsTransfer`) so a transfer only ever closes its own, and `importMap()` refuses to start while a JSON operation holds the progress - the mirror of the guard `downloadMap()` has. Two review-driven details worth flagging: the frontend only wires the dialog's cancel to the engine when the operation is actually cancelable, so a non-cancelable local XML import no longer turns a window-close into a spurious "Map download was canceled" message; and the standalone download/import dialog is now parented to the console (like the JSON one always was, and like #9507's package-download dialog), so it centres on and dies with the profile window. The three `#include <QApplication>` additions to `Host.cpp` / `dlgTriggerEditor.cpp` / `dlgConnectionProfiles.cpp` replace the transitive include they used to get from `XMLimport.h`; all three are already Qt Widgets consumers, so the audit count is unaffected. Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-opus-5 **Test case:** With a mapper window open, use a game that supports map download (or call `downloadMap()`) and confirm the progress dialog shows, updates, and its Abort cancels the download. Then with the mapper window closed, run `exportJsonMap()` and `importJsonMap()` on a large map and confirm the non-modal JSON progress dialog appears, updates its Areas/Rooms/Labels counts, and that clicking Abort during an import stops it with an "aborted by user" result. Load a local XML map (Settings -> Map -> load) and confirm closing its progress window does not print a "Map download was canceled" line. Everything should behave exactly as on `development`. #### Demo (before & after) https://github.com/user-attachments/assets/f1c62580-2d03-4e5b-a6ee-f6e2b78d113d
2026-08-02 15:33:07 +02:00
return mMapProgressCancelRequested;
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
}
void TMap::updateArea(int areaId)
Roomnames (#3992) * Map: Add an option to show room names below their IDs. This is a fairly straightforward extension. TODO: use a separate font. * basic support for a separate font for room names * Use black room names on light background * Room name display and font sizing fixes Room name display is now independent of room number display. The cut-off for the font size is lower (4 instead of 7). Room names are scaled as if the number 88 would be printed in the room box, which works for all practical purposes. Font size discovery is now done in floating point, and by scaling with factors 1.2 (up) and 1.05 (down) which is faster *and* looks way better. * Don't show room names in grid mode * Tweak font size calculation Ensure that we start with a reasonable font size * Added functions to get/set a room name's offset float x/y, relative to the room rectangle (and in its units). TODO: document in the wiki: getRoomNameOffset(id) setRoomNameOffset(id, x_offset, y_offset) * Save file version updated to 21 Added: * global: room name font + size adjustment * per room: label offset * remove LayoutDirection directives * Re-sorted the grid layout items in ui/profile_prefs * Fix room name placement directly under the room's rectangle, no strange offset * Add userdata flag "room.ui_showName" indicating whether to show room name * Move room label position to userdata * Cleanup The flag whether to display room labels (both globally and per-room) is now stored in userdata. Reverted: ad6d3 Re-sorted the grid layout items in ui/profile_prefs 76834 remove LayoutDirection directives 5d81e Save file version updated to 21 TODO: flipping the global flag crashes for no good reason. * Crash workaround Not inlining "setUserDataBool" triggers a double-free bug (Debian amd64, Qt 5.14.2-3, gcc 10.2.0-9). I'm investigating this; in the meantime, this patch should be an acceptable workaround. * Update src/mudlet-lua/lua/GUIUtils.lua * Appease codefactor * Hide showRoomNames checkbox if no room name infrastructure exists as exhibited by map userData "room.ui_showName" not being present at all Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2020-10-23 14:49:42 +02:00
{
static bool debounce;
if (!debounce) {
debounce = true;
infrastructure: use std::chrono literals for time durations (#9493) #### Brief overview of PR changes/additions Convert raw millisecond integer literals at time-duration call sites to `std::chrono` literals, and add `#include <chrono>` to each touched translation unit. Examples: - `QTimer::singleShot(0, ...)` → `QTimer::singleShot(0ms, ...)` - `mpTimerReplay->setInterval(1000)` → `setInterval(1s)` - `mPendingTimer.start(60000)` → `start(1min)` - `QObject::startTimer(50)` → `startTimer(50ms)` - `QTest::qWait(100)` → `QTest::qWait(100ms)` - `QThread::msleep(10)` → `QThread::sleep(10ms)` This is a semantics-preserving refactor - every duration is kept exactly equal to before (e.g. `1000` ms becomes `1s`, `60000` ms becomes `1min`). No behavioural change. #### Motivation for adding to Mudlet Chrono literals make time durations self-documenting and type-safe. `1s` / `100ms` read unambiguously where a bare `1000` / `100` forces the reader to remember each API's unit, and the compiler now rejects unit mismatches. Only genuine duration arguments were converted - loop counts, scroll-line counts, sizes, ports and the like were deliberately left as plain integers. All targeted APIs provide `std::chrono` overloads in the minimum supported Qt (6.8.2): `QTimer::singleShot`/`start`/`setInterval` (5.8), `QObject::startTimer` (5.9), `QThread::sleep(std::chrono::nanoseconds)` (6.6) and `QTest::qWait(std::chrono::milliseconds)` (6.7). #### Other info (issues closed, discussion etc) Test case: the full application builds cleanly and the entire functional `ctest` suite passes. The only failing test is the known, pre-existing `PasswordMigrationTest` LSan exit-leak (GTK3/fontconfig noise), which is unrelated to this change. Assisted-by: Claude:claude-opus-4-8
2026-07-25 20:24:31 +02:00
QTimer::singleShot(0ms, this, [this, areaId]() {
debounce = false;
Roomnames (#3992) * Map: Add an option to show room names below their IDs. This is a fairly straightforward extension. TODO: use a separate font. * basic support for a separate font for room names * Use black room names on light background * Room name display and font sizing fixes Room name display is now independent of room number display. The cut-off for the font size is lower (4 instead of 7). Room names are scaled as if the number 88 would be printed in the room box, which works for all practical purposes. Font size discovery is now done in floating point, and by scaling with factors 1.2 (up) and 1.05 (down) which is faster *and* looks way better. * Don't show room names in grid mode * Tweak font size calculation Ensure that we start with a reasonable font size * Added functions to get/set a room name's offset float x/y, relative to the room rectangle (and in its units). TODO: document in the wiki: getRoomNameOffset(id) setRoomNameOffset(id, x_offset, y_offset) * Save file version updated to 21 Added: * global: room name font + size adjustment * per room: label offset * remove LayoutDirection directives * Re-sorted the grid layout items in ui/profile_prefs * Fix room name placement directly under the room's rectangle, no strange offset * Add userdata flag "room.ui_showName" indicating whether to show room name * Move room label position to userdata * Cleanup The flag whether to display room labels (both globally and per-room) is now stored in userdata. Reverted: ad6d3 Re-sorted the grid layout items in ui/profile_prefs 76834 remove LayoutDirection directives 5d81e Save file version updated to 21 TODO: flipping the global flag crashes for no good reason. * Crash workaround Not inlining "setUserDataBool" triggers a double-free bug (Debian amd64, Qt 5.14.2-3, gcc 10.2.0-9). I'm investigating this; in the meantime, this patch should be an acceptable workaround. * Update src/mudlet-lua/lua/GUIUtils.lua * Appease codefactor * Hide showRoomNames checkbox if no room name infrastructure exists as exhibited by map userData "room.ui_showName" not being present at all Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2020-10-23 14:49:42 +02:00
#if defined(INCLUDE_3DMAPPER)
if (mpM) {
mpM->update();
}
Roomnames (#3992) * Map: Add an option to show room names below their IDs. This is a fairly straightforward extension. TODO: use a separate font. * basic support for a separate font for room names * Use black room names on light background * Room name display and font sizing fixes Room name display is now independent of room number display. The cut-off for the font size is lower (4 instead of 7). Room names are scaled as if the number 88 would be printed in the room box, which works for all practical purposes. Font size discovery is now done in floating point, and by scaling with factors 1.2 (up) and 1.05 (down) which is faster *and* looks way better. * Don't show room names in grid mode * Tweak font size calculation Ensure that we start with a reasonable font size * Added functions to get/set a room name's offset float x/y, relative to the room rectangle (and in its units). TODO: document in the wiki: getRoomNameOffset(id) setRoomNameOffset(id, x_offset, y_offset) * Save file version updated to 21 Added: * global: room name font + size adjustment * per room: label offset * remove LayoutDirection directives * Re-sorted the grid layout items in ui/profile_prefs * Fix room name placement directly under the room's rectangle, no strange offset * Add userdata flag "room.ui_showName" indicating whether to show room name * Move room label position to userdata * Cleanup The flag whether to display room labels (both globally and per-room) is now stored in userdata. Reverted: ad6d3 Re-sorted the grid layout items in ui/profile_prefs 76834 remove LayoutDirection directives 5d81e Save file version updated to 21 TODO: flipping the global flag crashes for no good reason. * Crash workaround Not inlining "setUserDataBool" triggers a double-free bug (Debian amd64, Qt 5.14.2-3, gcc 10.2.0-9). I'm investigating this; in the meantime, this patch should be an acceptable workaround. * Update src/mudlet-lua/lua/GUIUtils.lua * Appease codefactor * Hide showRoomNames checkbox if no room name infrastructure exists as exhibited by map userData "room.ui_showName" not being present at all Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2020-10-23 14:49:42 +02:00
#endif
if (mpMapper) {
if (mpMapper->mp2dMap) {
mpMapper->mp2dMap->mNewMoveAction = true;
mpMapper->mp2dMap->update();
}
}
emit signal_areaChanged(areaId);
});
Roomnames (#3992) * Map: Add an option to show room names below their IDs. This is a fairly straightforward extension. TODO: use a separate font. * basic support for a separate font for room names * Use black room names on light background * Room name display and font sizing fixes Room name display is now independent of room number display. The cut-off for the font size is lower (4 instead of 7). Room names are scaled as if the number 88 would be printed in the room box, which works for all practical purposes. Font size discovery is now done in floating point, and by scaling with factors 1.2 (up) and 1.05 (down) which is faster *and* looks way better. * Don't show room names in grid mode * Tweak font size calculation Ensure that we start with a reasonable font size * Added functions to get/set a room name's offset float x/y, relative to the room rectangle (and in its units). TODO: document in the wiki: getRoomNameOffset(id) setRoomNameOffset(id, x_offset, y_offset) * Save file version updated to 21 Added: * global: room name font + size adjustment * per room: label offset * remove LayoutDirection directives * Re-sorted the grid layout items in ui/profile_prefs * Fix room name placement directly under the room's rectangle, no strange offset * Add userdata flag "room.ui_showName" indicating whether to show room name * Move room label position to userdata * Cleanup The flag whether to display room labels (both globally and per-room) is now stored in userdata. Reverted: ad6d3 Re-sorted the grid layout items in ui/profile_prefs 76834 remove LayoutDirection directives 5d81e Save file version updated to 21 TODO: flipping the global flag crashes for no good reason. * Crash workaround Not inlining "setUserDataBool" triggers a double-free bug (Debian amd64, Qt 5.14.2-3, gcc 10.2.0-9). I'm investigating this; in the meantime, this patch should be an acceptable workaround. * Update src/mudlet-lua/lua/GUIUtils.lua * Appease codefactor * Hide showRoomNames checkbox if no room name infrastructure exists as exhibited by map userData "room.ui_showName" not being present at all Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2020-10-23 14:49:42 +02:00
}
}
QColor TMap::getColor(int id)
{
QColor color;
TRoom* room = mpRoomDB->getRoom(id);
if (!room) {
return color;
}
int env = room->environment;
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
if (mEnvColors.contains(env)) {
env = mEnvColors.value(env);
} else {
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
if (!mCustomEnvColors.contains(env)) {
env = 1;
}
}
switch (env) {
case 1:
color = mpHost->mRed_2;
break;
case 2:
color = mpHost->mGreen_2;
break;
case 3:
color = mpHost->mYellow_2;
break;
case 4:
color = mpHost->mBlue_2;
break;
case 5:
color = mpHost->mMagenta_2;
break;
case 6:
color = mpHost->mCyan_2;
break;
case 7:
color = mpHost->mWhite_2;
break;
case 8:
color = mpHost->mBlack_2;
break;
case 9:
color = mpHost->mLightRed_2;
break;
case 10:
color = mpHost->mLightGreen_2;
break;
case 11:
color = mpHost->mLightYellow_2;
break;
case 12:
color = mpHost->mLightBlue_2;
break;
case 13:
color = mpHost->mLightMagenta_2;
break;
case 14:
color = mpHost->mLightCyan_2;
break;
case 15:
color = mpHost->mLightWhite_2;
break;
case 16:
color = mpHost->mLightBlack_2;
break;
default: //user defined room color
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
if (!mCustomEnvColors.contains(env)) {
if (16 < env && env < 232) {
quint8 const base = env - 16;
quint8 r = base / 36;
quint8 g = (base - (r * 36)) / 6;
quint8 b = (base - (r * 36)) - (g * 6);
r = r == 0 ? 0 : (r - 1) * 40 + 95;
g = g == 0 ? 0 : (g - 1) * 40 + 95;
b = b == 0 ? 0 : (b - 1) * 40 + 95;
color = QColor(r, g, b, 255);
} else if (231 < env && env < 256) {
quint8 const k = ((env - 232) * 10) + 8;
color = QColor(k, k, k, 255);
}
break;
}
Enhance: import/export map as JSON (#4546) This is so that a crowd sourced map might be edited in a collaborative manner. The first stage is to make sufficient of the entire map details be exported/imported in a modular (by area) fashion. Include Lua functions `exportJsonMap(pathFileName)` and `importJsonMap(pathFileName)` to perform the whole map export and import functions. Also, rename `(QMultiMap<int, QPair<int, int>>) TArea::exits` to: `TArea::mAreaExits` because the old name was such a common word in our source code it was hard to find the uses of this member. This format has been constructed so as to not mention the most common, or default values for some items - so as to minimise details that have to be included on the basis they can be assumed when reconstructing them on the other end. On the other hand the whole file is compressible so for storage (but not for diff/git work) archiving / compressing the file is recommended! For instance a binary map file I have is 18.6MB which produced a 25.8MB JSON file which I was able to compress down to 2.9MB - obviously this is *very* content dependent, so other's Miles-May-Vary... As the export process is not that fast include a progress dialogue that shows how many areas, map labels and rooms have been processed into the JSON format. For a 20K room map with 40 odd areas and around 800 map labels (which are awkward to convert to a text-like form) this can take 30 seconds on my 1.8GHz 4 Core PC! CodeFactor had a recommendation about a constant that I was using to set the dimension of a `char[]` (array) - it felt a compile time `constexpr` was a better thing to use. Revised to make Cancel button work in big areas: Although the existing code would abort at the end of an area, for some humongous maps with a few very large areas it is also a good idea to check for the cancel button being pressed each time the progress bar is updated. Renamed `(QMap<int, int>) TMap::envColors` to `TMap::mEnvColors` and `(QMap<int, QColor>) Tmap::customEnvColors` to `TMap::mCustomEnvColors` so that it is clearer that they are members of the `TMap` class. Add alpha component to end of list of (now four) 0 to 255 integer values returned by `getCustomEnvColorTable()` - as the corresponding setter does allow one to be provided. Move initialisers for TMap, TRoomDB, TRoom and TArea to header file where possible. As per Issue #4578. Move the default and unnamed area names from TRoomDB to TMap - as it made setting them up easier (though one of them does need to be initialised before the normal TRoomDB instance associated with the TMap is itself initialised. This meant putting these private members near the top of the header file even though we normally put private ones down the bottom. Refactor: move JSON colour writing/reading code from TArea/TRoom to TMap The code is common to all three classes so can be shared. At the same time make it explicit in the key as to whether there is an alpha component so the colour is a 24Bit opaque one or a 32Bit one with transparency. Revise: peer-review items and other tweaks Note that this revises the format version to be 1.000 (ready for release) so, although the format has not changed, any recent files produced during evaluation will need to be hand edited to change the line: "formatVersion": 0.003, to: "formatVersion": 1.000, in order to read them now. Switch to "range based" for-loops for some of the JSON additions. Fixup: ensure partially built new TRoomDB is destroyed if reading aborted Not doing this would cause a resource leak if the abort button was clicked during importation of a Json map file. Revise: disable writing out Room highlighting details It has been pointed out that the binary map format does not save the room highlighting details either - so replicate that behaviour for the moment. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2021-02-14 23:44:55 +00:00
color = mCustomEnvColors.value(env);
}
return color;
}
Infrastructure: move away from constructor initialisation lists - part 2 (#5937) For classes from "T2*" to "TM*" (approximately)... I have steered away from using `{}` to initialise simple, POD data types in favour of explicitly stating what their default values are. Also: * remove unused `(QColor) TAction::mButtonColor` and it's associated getter and setter. Also remove the save code from the `XMLexport` class and ensure it is skipped and silently discarded in the load code in `XMLimport`. * Make `private` some members of the `TFlipButton` class that probably weren't ever intended to be `public` * Remove unneeded named argument for `lua_State*` type in many (but not all) function declarations in `TLuaInterpreter.h` file - they aren't needed and whether an `L` was present or not seems to entirely down to the whim of the individual coder of each function...! * Rejig some of the initiliasations in the `TLuaInterpreter` class * Refactor a chunk of code n the `TMap` class used to (re)initialise the 16 colours user settable from the preferences dialogue to a method: `(void) TMap::restore16ColorSet()` - so that it can be used in three other places as well as the constuctor. * Remove unused `(int) T2DMap::gzoom`. * Add missing `TMediaData.h` file to qmake project file. Note: `QPointer<T>` instances do NOT need initialisation, they are automagically instantiated with a `nullptr` value. Revised to change code to fit in with PR #6133 There were some pre-Qt 5.14.0 version checks that are no longer relevant. Signed-off-by: Stephen Lyons <slysven@virginmedia.com> Co-authored-by: Vadim Peretokin <vperetokin@gmail.com>
2022-06-27 20:36:51 +01:00
void TMap::restore16ColorSet()
{
mCustomEnvColors[257] = mpHost->mRed_2;
mCustomEnvColors[258] = mpHost->mGreen_2;
mCustomEnvColors[259] = mpHost->mYellow_2;
mCustomEnvColors[260] = mpHost->mBlue_2;
mCustomEnvColors[261] = mpHost->mMagenta_2;
mCustomEnvColors[262] = mpHost->mCyan_2;
mCustomEnvColors[263] = mpHost->mWhite_2;
mCustomEnvColors[264] = mpHost->mBlack_2;
mCustomEnvColors[265] = mpHost->mLightRed_2;
mCustomEnvColors[266] = mpHost->mLightGreen_2;
mCustomEnvColors[267] = mpHost->mLightYellow_2;
mCustomEnvColors[268] = mpHost->mLightBlue_2;
mCustomEnvColors[269] = mpHost->mLightMagenta_2;
mCustomEnvColors[270] = mpHost->mLightCyan_2;
mCustomEnvColors[271] = mpHost->mLightWhite_2;
mCustomEnvColors[272] = mpHost->mLightBlack_2;
}
void TMap::setUnsaved(const char* fromWhere)
{
#if !defined(DEBUG_MAPAUTOSAVE)
Q_UNUSED(fromWhere)
#else
QString nowString = QDateTime::currentDateTimeUtc().toString("HH:mm:ss.zzz");
qDebug().nospace().noquote() << "TMap::setUnsaved(...) INFO - called at: " << nowString << " from: " << fromWhere << ".";
#endif
mUnsavedMap = true;
}
void TMap::setSaveError(bool state)
{
if (mSaveError != state) {
mSaveError = state;
emit signal_saveErrorChanged(state);
}
}
void TMap::setDefaultAreaShown(bool state)
{
if (mShowDefaultArea != state) {
mShowDefaultArea = state;
if (!mpMapper.isNull()) {
mpMapper->updateAreaComboBox();
}
}
}