2010-08-25 00:41:43 +02:00
/***************************************************************************
2014-08-15 02:11:43 -07: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 *
2026-04-16 14:30:33 +01:00
* 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"
2014-08-15 02:11:43 -07:00
# 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"
2021-01-17 09:02:23 +00:00
# include "TMapLabel.h"
2026-01-18 11:41:17 +01:00
# include "TMapViewManager.h"
2014-08-15 02:11:43 -07:00
# 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"
2025-11-19 02:57:25 +01:00
# include "TLuaInterpreter.h"
2021-02-11 18:05:40 +01:00
# include "mapInfoContributorManager.h"
2022-06-27 20:36:51 +01:00
# include "mudlet.h"
2014-08-15 02:11:43 -07:00
2026-01-08 21:04:24 +01:00
# 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>
2018-06-07 00:07:32 +01:00
# include <QElapsedTimer>
2026-01-08 21:04:24 +01:00
# 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>
2019-08-15 11:56:11 +02:00
# include <QPainter>
2026-01-08 21:04:24 +01:00
# 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>
2026-01-08 21:04:24 +01:00
# 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
2026-01-19 07:31:50 +01: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 ( ) ) ;
}
}
}
2026-02-04 08:30:01 +01:00
// 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 ( ) ) ;
}
}
}
2026-01-19 07:31:50 +01:00
} // anonymous namespace
2019-02-22 06:10:41 +00:00
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 ) )
2026-01-18 11:41:17 +01:00
, mpViewManager ( new TMapViewManager ( pH , this ) )
2017-06-26 16:46:54 +02:00
, mpHost ( pH )
2019-02-22 06:10:41 +00:00
, mProfileName ( profileName )
2010-08-25 00:41:43 +02:00
{
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
2022-11-24 08:42:28 +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...!
2017-06-26 16:46:54 +02:00
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
2021-02-11 18:05:40 +01:00
mMapInfoContributorManager = new MapInfoContributorManager ( this , pH ) ;
2018-07-26 13:30:02 +02:00
connect ( mpNetworkAccessManager , & QNetworkAccessManager : : finished , this , & TMap : : slot_replyFinished ) ;
2010-08-25 00:41:43 +02:00
}
2016-03-14 12:24:01 +00:00
TMap : : ~ TMap ( )
{
2017-06-26 16:46:54 +02:00
if ( ! mStoredMessages . isEmpty ( ) ) {
2016-05-03 04:58:31 +01:00
qWarning ( ) < < " TMap::~TMap() Instance being destroyed before it could display some messages, \n "
< < " messages are: \n "
< < " ------------ " ;
2026-04-16 14:30:33 +01:00
for ( const auto & message : std : : as_const ( mStoredMessages ) ) {
2017-06-26 16:46:54 +02:00
qWarning ( ) < < message < < " \n ------------ " ;
2016-03-14 12:24:01 +00:00
}
}
2014-08-27 20:24:25 -07:00
}
2013-03-11 16:05:18 -04: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:
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 ( ) ;
2025-09-19 13:11:00 +07: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
// mSaveVersion is not reset - so that any new Mudlet map file saves are to
// whatever version was previously set/deduced
2021-12-21 03:03:24 +00:00
// 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 ( ) ;
2025-09-19 13:11:00 +07:00
auto map = mpMapper - > mp2dMap ;
if ( map ) {
map - > mMultiSelectionListWidget . clear ( ) ;
map - > mMultiSelectionListWidget . hide ( ) ;
}
2021-12-21 03:03:24 +00:00
}
2013-03-11 16:05:18 -04:00
}
2026-04-17 01:18:40 +01:00
// The supplied message should contain a localised message and no "WARNING:" or other prefixes:
void TMap : : logError ( const QString & msg )
2013-05-22 10:15:29 +02:00
{
2017-06-26 16:46:54 +02:00
if ( mpHost - > mpEditorDialog ) {
2026-04-17 01:18:40 +01:00
/*: 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 . */
2026-04-25 13:02:24 +02:00
mpHost - > mpEditorDialog - > mpErrorConsole - > print ( tr ( " [MAP ERROR:] %1 " ) . arg ( msg ) . append ( QChar : : LineFeed ) , QColor ( 255 , 128 , 0 ) , QColor ( Qt : : black ) ) ;
2013-05-22 10:15:29 +02: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
// 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
2024-08-21 08:13:37 +02:00
bool TMap : : setRoomArea ( int id , int area , bool deferAreaRecalculations )
2011-06-16 09:49:34 +02:00
{
2017-06-26 16:46:54 +02:00
TRoom * pR = mpRoomDB - > getRoom ( id ) ;
if ( ! pR ) {
2026-04-25 13:02:24 +02:00
logError ( tr ( " Can not set room with RoomID %1 to AreaID %2. Room does not exist! " ) . arg ( QString : : number ( id ) , QString : : number ( area ) ) ) ;
2015-01-09 03:51:50 +00:00
return false ;
}
2017-06-26 16:46:54 +02:00
TArea * pA = mpRoomDB - > getArea ( area ) ;
if ( ! pA ) {
2020-11-05 10:56:26 +01:00
// Uh oh, the area doesn't seem to exist as a TArea instance, let's check
2015-06-28 05:20:12 +01:00
// to see if it exists as a name only:
2017-06-26 16:46:54 +02:00
if ( ! mpRoomDB - > getAreaNamesMap ( ) . contains ( area ) ) {
2015-06-28 05:20:12 +01:00
// Ah, no it doesn't so moan:
2026-04-25 13:02:24 +02:00
logError ( tr ( " Can not set room with RoomID %1 to AreaID %2. Area does not exist! " ) . arg ( QString : : number ( id ) , QString : : number ( area ) ) ) ;
2015-06-28 05:20:12 +01:00
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...
2013-05-22 10:15:29 +02:00
}
2011-06-16 09:49:34 +02:00
2024-08-21 08:13:37 +02:00
const bool result = pR - > setArea ( area , deferAreaRecalculations ) ;
2017-06-26 16:46:54 +02:00
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 ;
2022-11-11 05:01:28 +00:00
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
}
2017-06-26 16:46:54 +02:00
bool TMap : : addRoom ( int id )
2010-09-07 20:35:32 +02:00
{
2022-11-11 05:01:28 +00:00
if ( mpRoomDB - > addRoom ( id ) ) {
2017-06-26 16:46:54 +02:00
mMapGraphNeedsUpdate = true ;
2022-11-11 05:01:28 +00:00
setUnsaved ( __func__ ) ;
return true ;
2017-06-26 16:46:54 +02:00
}
2022-11-11 05:01:28 +00:00
return false ;
2010-09-07 20:35:32 +02:00
}
2017-06-26 16:46:54 +02:00
bool TMap : : setRoomCoordinates ( int id , int x , int y , int z )
2010-09-07 20:35:32 +02:00
{
2017-06-26 16:46:54 +02:00
TRoom * pR = mpRoomDB - > getRoom ( id ) ;
if ( ! pR ) {
return false ;
}
2010-09-07 20:35:32 +02:00
2026-04-23 00:18:21 -04: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 ) ;
}
}
2024-12-09 14:29:13 +00:00
pR - > setCoordinates ( x , y , z ) ;
2010-12-28 23:31:03 +01:00
2022-11-11 05:01:28 +00:00
setUnsaved ( __func__ ) ;
2010-09-07 20:35:32 +02:00
return true ;
}
2017-06-26 16:46:54 +02:00
int compSign ( int a , int b )
{
2011-10-11 04:09:28 +02:00
return ( a < 0 ) = = ( b < 0 ) ;
}
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
{
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 " ) ;
2021-10-02 21:09:23 +01:00
TRoom * pFromR = mpRoomDB - > getRoom ( fromRoomId ) ;
if ( ! pFromR ) {
2021-12-07 06:21:39 +01:00
return qsl ( " fromID (%1) does not exist " ).arg(fromRoomId) ;
2016-03-08 08:35:07 +00:00
}
2023-05-14 15:06:15 +02:00
const int area = pFromR - > getArea ( ) ;
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)) ;
2017-06-26 16:46:54 +02:00
}
2021-10-02 21:09:23 +01:00
2023-05-14 15:06:15 +02:00
const int reverseDir = scmReverseDirections . value ( dirType ) ;
2024-03-11 15:40:56 +00:00
const QVector3D unitVector = scmUnitVectors . value ( dirType ) ;
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!
2023-05-14 15:06:15 +02:00
const int ux = qRound ( unitVector . x ( ) ) ;
const int uy = qRound ( unitVector . y ( ) ) ;
const int uz = qRound ( unitVector . z ( ) ) ;
2024-12-09 14:29:13 +00:00
const int rx = pFromR - > x ( ) ;
const int ry = pFromR - > y ( ) ;
const int rz = pFromR - > z ( ) ;
2021-10-02 21:09:23 +01:00
int dx = 0 ;
int dy = 0 ;
int dz = 0 ;
2017-06-26 16:46:54 +02:00
TArea * pA = mpRoomDB - > getArea ( area ) ;
if ( ! pA ) {
2021-12-07 06:21:39 +01:00
return qsl ( " fromID (%1) room does not have an area " ).arg(fromRoomId) ;
2016-03-08 08:35:07 +00:00
}
2021-10-02 21:09:23 +01:00
2017-06-26 16:46:54 +02:00
QSetIterator < int > itRoom ( pA - > getAreaRooms ( ) ) ;
while ( itRoom . hasNext ( ) ) {
2021-10-02 21:09:23 +01:00
auto toRoom = itRoom . next ( ) ;
auto pToR = mpRoomDB - > getRoom ( toRoom ) ;
if ( ! pToR | | pToR - > getId ( ) = = fromRoomId ) {
2016-03-08 08:35:07 +00:00
continue ;
}
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 ) ) {
2016-03-08 08:35:07 +00:00
continue ;
}
2021-10-02 21:09:23 +01:00
2017-06-26 16:46:54 +02:00
if ( uz ) {
2024-12-09 14:29:13 +00:00
dz = pToR - > z ( ) - rz ;
2017-06-26 16:46:54 +02:00
if ( ! compSign ( dz , uz ) | | ! dz ) {
2016-03-08 08:35:07 +00:00
continue ;
}
2021-10-02 21:09:23 +01:00
2017-06-26 16:46:54 +02:00
} else {
2011-10-11 04:09:28 +02:00
//to avoid lower/upper floors from stealing stubs
2024-12-09 14:29:13 +00:00
if ( pToR - > z ( ) ! = rz ) {
2016-03-08 08:35:07 +00:00
continue ;
}
2011-10-11 04:09:28 +02:00
}
2021-10-02 21:09:23 +01:00
2017-06-26 16:46:54 +02:00
if ( ux ) {
2024-12-09 14:29:13 +00:00
dx = pToR - > x ( ) - rx ;
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
2017-06-26 16:46:54 +02:00
continue ;
2016-03-08 08:35:07 +00:00
}
2021-10-02 21:09:23 +01:00
2017-06-26 16:46:54 +02:00
} else {
2011-10-11 04:09:28 +02:00
//to avoid rooms on same plane from stealing stubs
2024-12-09 14:29:13 +00:00
if ( pToR - > x ( ) ! = rx ) {
2016-03-08 08:35:07 +00:00
continue ;
}
2011-10-11 04:09:28 +02:00
}
2021-10-02 21:09:23 +01:00
2017-06-26 16:46:54 +02:00
if ( uy ) {
2024-12-09 14:29:13 +00:00
dy = pToR - > y ( ) - ry ;
2011-10-11 04:09:28 +02:00
//if the sign is the SAME here we keep it b/c we flip our y coordinate.
2017-06-26 16:46:54 +02:00
if ( compSign ( dy , uy ) | | ! dy ) {
2011-10-11 04:09:28 +02:00
continue ;
2016-03-08 08:35:07 +00:00
}
2021-10-02 21:09:23 +01:00
2017-06-26 16:46:54 +02:00
} else {
2011-10-11 04:09:28 +02:00
//to avoid rooms on same plane from stealing stubs
2024-12-09 14:29:13 +00:00
if ( pToR - > y ( ) ! = ry ) {
2016-03-08 08:35:07 +00:00
continue ;
}
2011-10-11 04:09:28 +02:00
}
2021-10-02 21:09:23 +01:00
2017-06-26 16:46:54 +02:00
meanSquareDistance = dx * dx + dy * dy + dz * dz ;
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 ;
2017-06-26 16:46:54 +02:00
minDistance = meanSquareDistance ;
2011-10-11 04:09:28 +02:00
}
}
2021-10-02 21:09:23 +01:00
2017-06-26 16:46:54 +02:00
if ( minDistanceRoom ) {
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!
2021-12-07 06:21:39 +01:00
return qsl ( " nearest room in the indicated direction (%1) does not exist " ).arg(minDistanceRoom) ;
2016-03-08 08:35:07 +00:00
}
2021-10-02 21:09:23 +01:00
setExit ( fromRoomId , minDistanceRoom , dirType ) ;
2022-06-27 20:36:51 +01:00
setExit ( minDistanceRoom , fromRoomId , scmReverseDirections . value ( dirType ) ) ;
2022-11-11 05:01:28 +00:00
setUnsaved ( __func__ ) ;
2021-10-02 21:09:23 +01:00
return { } ;
}
2021-12-07 06:21:39 +01:00
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 ) ) ;
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 ) {
2021-12-07 06:21:39 +01:00
return qsl ( " fromID (%1) does not exist " ).arg(fromRoomId) ;
2021-10-02 21:09:23 +01:00
}
if ( toRoomId = = fromRoomId ) {
2021-12-07 06:21:39 +01:00
return qsl ( " fromID and toID are the same (%1) " ).arg(fromRoomId) ;
2021-10-02 21:09:23 +01:00
}
auto pToR = mpRoomDB - > getRoom ( toRoomId ) ;
if ( ! pToR ) {
2021-12-07 06:21:39 +01:00
return qsl ( " toID (%1) room does not exist " ).arg(toRoomId) ;
2021-10-02 21:09:23 +01:00
}
if ( pFromR - > exitStubs . isEmpty ( ) ) {
2021-12-07 06:21:39 +01:00
return qsl ( " fromID (%1) does not have any stub exits " ).arg(fromRoomId) ;
2021-10-02 21:09:23 +01:00
}
if ( pToR - > exitStubs . isEmpty ( ) ) {
2021-12-07 06:21:39 +01:00
return qsl ( " toID (%1) does not have any stub exits " ).arg(toRoomId) ;
2021-10-02 21:09:23 +01:00
}
2023-05-14 15:06:15 +02:00
QSet < int > const fromRoomStubs { pFromR - > exitStubs . cbegin ( ) , pFromR - > exitStubs . cend ( ) } ;
2021-10-02 21:09:23 +01:00
QListIterator < int > itToRoomStubs { pToR - > exitStubs } ;
QSet < int > toReverseStubDirections ;
while ( itToRoomStubs . hasNext ( ) ) {
auto direction = itToRoomStubs . next ( ) ;
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 ) ) ;
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 ( ) ) {
2021-12-07 06:21:39 +01:00
return qsl ( " no pairs of reverse stubs found between rooms %1 and %2 " ) . arg ( QString : : number ( fromRoomId ) , QString : : number ( toRoomId ) ) ;
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 ( ) ;
2021-12-07 06:21:39 +01:00
useableStubDirectionTexts < < qsl ( " '%1' (%2) " ) . arg ( TRoom : : dirCodeToString ( direction ) , QString : : number ( direction ) ) ;
2011-10-11 04:09:28 +02:00
}
2021-12-07 06:21:39 +01:00
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 " )
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:
2023-05-14 15:06:15 +02:00
const int usableStubDirection = * ( usableStubDirections . constBegin ( ) ) ;
2021-10-02 21:09:23 +01:00
setExit ( fromRoomId , toRoomId , usableStubDirection ) ;
2022-06-27 20:36:51 +01:00
setExit ( toRoomId , fromRoomId , scmReverseDirections . value ( usableStubDirection ) ) ;
2022-11-11 05:01:28 +00:00
setUnsaved ( __func__ ) ;
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 )
{
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 " ) ;
2021-10-02 21:09:23 +01:00
auto pFromR = mpRoomDB - > getRoom ( fromRoomId ) ;
if ( ! pFromR ) {
2021-12-07 06:21:39 +01:00
return qsl ( " fromID (%1) does not exist " ).arg(fromRoomId) ;
2021-10-02 21:09:23 +01:00
}
if ( toRoomId = = fromRoomId ) {
2021-12-07 06:21:39 +01:00
return qsl ( " fromID and toID are the same (%1) " ).arg(fromRoomId) ;
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 ) {
2021-12-07 06:21:39 +01:00
return qsl ( " toID (%1) room does not exist " ).arg(toRoomId) ;
2011-10-11 04:09:28 +02:00
}
2021-10-02 21:09:23 +01:00
2022-06-27 20:36:51 +01:00
if ( ! pToR - > exitStubs . contains ( scmReverseDirections . value ( dirType ) ) ) {
2021-12-07 06:21:39 +01:00
return qsl ( " toID (%1) does not have an exit stub in the reverse direction '%2' (%3) of that given '%4' (%5) " )
2021-10-02 21:09:23 +01:00
. arg ( QString : : number ( toRoomId ) ,
2022-06-27 20:36:51 +01:00
TRoom : : dirCodeToString ( scmReverseDirections . value ( dirType ) ) ,
QString : : number ( scmReverseDirections . value ( dirType ) ) ,
2021-10-02 21:09:23 +01:00
TRoom : : dirCodeToString ( dirType ) ,
QString : : number ( dirType ) ) ;
}
setExit ( fromRoomId , toRoomId , dirType ) ;
2022-06-27 20:36:51 +01:00
setExit ( toRoomId , fromRoomId , scmReverseDirections . value ( dirType ) ) ;
2022-11-11 05:01:28 +00:00
setUnsaved ( __func__ ) ;
2021-10-02 21:09:23 +01:00
return { } ;
2011-10-11 04:09:28 +02:00
}
2017-06-26 16:46:54 +02:00
int TMap : : createNewRoomID ( int minimumId )
2010-09-07 20:35:32 +02:00
{
2016-04-14 20:44:07 +01:00
int _id = 0 ;
2017-06-26 16:46:54 +02:00
if ( minimumId > 0 ) {
2016-04-14 20:44:07 +01:00
_id = minimumId - 1 ;
2010-09-07 20:35:32 +02:00
}
2016-04-14 20:44:07 +01:00
do {
; // Empty loop as increment done in test
2017-06-26 16:46:54 +02:00
} while ( mpRoomDB - > getRoom ( + + _id ) ) ;
2016-04-14 20:44:07 +01:00
return _id ;
2010-09-07 20:35:32 +02:00
}
2017-06-26 16:46:54 +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.
2017-06-26 16:46:54 +02:00
TRoom * pR = mpRoomDB - > getRoom ( from ) ;
TRoom * pR_to = mpRoomDB - > getRoom ( to ) ;
2013-03-22 12:47:58 +01:00
2017-06-26 16:46:54 +02: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 ;
}
2017-06-26 16:46:54 +02:00
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 ;
}
2017-06-26 16:46:54 +02:00
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
2017-06-26 16:46:54 +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 ) ;
2011-05-27 20:17:31 +02:00
mMapGraphNeedsUpdate = true ;
2017-06-26 16:46:54 +02:00
TArea * pA = mpRoomDB - > getArea ( pR - > getArea ( ) ) ;
if ( ! pA ) {
2013-12-22 21:02:25 -05:00
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 ) ;
2022-11-11 05:01:28 +00:00
setUnsaved ( __func__ ) ;
2013-05-26 11:47:15 +02:00
return ret ;
2010-09-07 20:35:32 +02:00
}
2016-03-14 12:24:01 +00:00
void TMap : : audit ( )
2010-08-25 00:41:43 +02:00
{
2012-05-15 23:16:58 +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 ( ) ;
2016-03-14 12:24:01 +00:00
{ // Blocked - just to limit the scope of infoMsg...!
2023-05-14 15:06:15 +02:00
const QString infoMsg = tr ( " [ INFO ] - Map audit starting... " ) ;
2017-06-26 16:46:54 +02:00
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
}
2016-03-14 12:24:01 +00:00
// The old mpRoomDB->initAreasForOldMaps() was a subset of these checks
QHash < int , int > roomRemapping ; // These are populated by the auditRooms(...)
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
2017-06-26 16:46:54 +02: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+)
2016-03-14 12:24:01 +00:00
2017-06-26 16:46:54 +02:00
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 ( ) ;
2023-05-14 15:06:15 +02:00
const int areaID = itArea . key ( ) ;
2021-01-17 09:02:23 +00:00
TArea * pArea = mpRoomDB - > getArea ( areaID ) ;
2025-11-28 03:27:01 +01:00
if ( ! pArea ) {
continue ;
}
2021-01-17 09:02:23 +00:00
if ( ! pArea - > mMapLabels . isEmpty ( ) ) {
2023-05-14 15:06:15 +02:00
QList < int > const labelIDList = pArea - > mMapLabels . keys ( ) ;
for ( const int & i : labelIDList ) {
TMapLabel const l = pArea - > mMapLabels . value ( i ) ;
2017-06-26 16:46:54 +02:00
if ( l . pix . isNull ( ) ) {
2021-01-17 09:02:23 +00:00
// Note that two of the last three arguments here
// (false, 40.0) are not the defaults (true, 30.0) used
// now:
Add: give map label text the ability to have an outline (#7598)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Add an outline colour chooser to map label creation window in mapper.
Update createMapLabel Lua function to reflect this as well. Adds three
optional arguments to the end of createMapLabel( ..., outlineRed,
outlineGreen, outlineBlue), default to the same colour as foreground if
not specified.
Also, chosen colours weren't being saved from one dialog to the next
forcing unnecessary typing to replicate a colour scheme when creating
multiple labels, so fix this and allow chosen colours to also save
across Mudlet restarts as well.
#### Motivation for adding to Mudlet
Better user experience, more map design options, prettier maps.
#### Other info (issues closed, discussion etc)
- The outline width is only 1 pixel, but as fonts get smaller this
starts to become increasingly larger compared to the width of the small
font. Zoomed in fonts (or larger than 16 on my display) typically look
better.
- Based on this work I think it would be fairly trivial to add drop
shadows, mirroring and other text effects.

Zoomed in;

closes #2861
/claim #2861
2024-12-27 12:07:37 +04:00
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 ) ;
2017-06-26 16:46:54 +02:00
if ( newID > - 1 ) {
if ( mudlet : : self ( ) - > showMapAuditErrors ( ) ) {
2023-05-14 15:06:15 +02:00
const QString msg = tr ( " [ INFO ] - CONVERTING: old style label, areaID:%1 labelID:%2. " ) . arg ( areaID ) . arg ( i ) ;
2016-05-03 04:58:31 +01:00
postMessage ( msg ) ;
}
2017-06-26 16:46:54 +02:00
appendAreaErrorMsg ( areaID , tr ( " [ INFO ] - Converting old style label id: %1. " ) . arg ( i ) ) ;
2021-01-17 09:02:23 +00:00
pArea - > mMapLabels [ i ] = pArea - > mMapLabels . take ( newID ) ;
2017-06-26 16:46:54 +02:00
} else {
if ( mudlet : : self ( ) - > showMapAuditErrors ( ) ) {
2023-05-14 15:06:15 +02:00
const QString msg = tr ( " [ WARN ] - CONVERTING: cannot convert old style label in area with id: %1, label id is: %2. " ) . arg ( areaID ) . arg ( i ) ;
2016-05-03 04:58:31 +01:00
postMessage ( msg ) ;
}
2017-06-26 16:46:54 +02:00
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
}
}
2017-06-26 16:46:54 +02:00
if ( ( l . size . width ( ) > std : : numeric_limits < qreal > : : max ( ) ) | | ( l . size . width ( ) < - std : : numeric_limits < qreal > : : max ( ) ) ) {
2021-01-17 09:02:23 +00:00
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
}
2017-06-26 16:46:54 +02:00
if ( ( l . size . height ( ) > std : : numeric_limits < qreal > : : max ( ) ) | | ( l . size . height ( ) < - std : : numeric_limits < qreal > : : max ( ) ) ) {
2021-01-17 09:02:23 +00:00
pArea - > mMapLabels [ i ] . size . setHeight ( l . pix . height ( ) ) ;
2012-12-29 02:16:28 +01:00
}
2013-03-03 12:22:58 -05:00
}
2012-12-29 02:16:28 +01:00
}
}
}
2016-03-14 12:24:01 +00:00
2017-06-26 16:46:54 +02:00
mpRoomDB - > auditRooms ( roomRemapping , areaRemapping ) ;
2016-03-14 12:24:01 +00:00
// 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
2017-06-26 16:46:54 +02:00
QMapIterator < int , TArea * > itArea ( mpRoomDB - > getAreaMap ( ) ) ;
while ( itArea . hasNext ( ) ) {
2016-03-14 12:24:01 +00:00
itArea . next ( ) ;
2024-12-09 14:29:13 +00:00
itArea . value ( ) - > clean ( ) ;
2016-03-14 12:24:01 +00:00
}
{ // Blocked - just to limit the scope of infoMsg...!
2023-05-14 15:06:15 +02:00
const QString infoMsg = tr ( " [ OK ] - Auditing of map completed (%1s). Enjoy your game... " ) . arg ( _time . nsecsElapsed ( ) * 1.0e-9 , 0 , ' f ' , 2 ) ;
2017-06-26 16:46:54 +02:00
postMessage ( infoMsg ) ;
appendErrorMsg ( infoMsg ) ;
2016-03-14 12:24:01 +00:00
}
2017-07-02 05:58:03 +02:00
2025-09-12 10:49:47 +07:00
mpHost - > getLuaInterpreter ( ) - > condenseMapLoad ( ) ;
2010-08-25 00:41:43 +02:00
}
2024-12-09 14:29:13 +00:00
// This may be duplicating TArea class functionality:
2017-06-26 16:46:54 +02:00
QList < int > TMap : : detectRoomCollisions ( int id )
2010-12-28 23:31:03 +01:00
{
2016-03-08 08:35:07 +00:00
QList < int > collList ;
2017-06-26 16:46:54 +02:00
TRoom * pR = mpRoomDB - > getRoom ( id ) ;
if ( ! pR ) {
2016-03-08 08:35:07 +00:00
return collList ;
2010-12-28 23:31:03 +01:00
}
2023-05-14 15:06:15 +02:00
const int area = pR - > getArea ( ) ;
2024-12-09 14:29:13 +00:00
const int x = pR - > x ( ) ;
const int y = pR - > y ( ) ;
const int z = pR - > z ( ) ;
2017-06-26 16:46:54 +02:00
TArea * pA = mpRoomDB - > getArea ( area ) ;
if ( ! pA ) {
2016-03-08 08:35:07 +00:00
return collList ;
2010-12-28 23:31:03 +01:00
}
2016-03-08 08:35:07 +00:00
2017-06-26 16:46:54 +02:00
QSetIterator < int > itRoom ( pA - > getAreaRooms ( ) ) ;
while ( itRoom . hasNext ( ) ) {
2023-05-14 15:06:15 +02:00
const int checkRoomId = itRoom . next ( ) ;
2017-06-26 16:46:54 +02:00
pR = mpRoomDB - > getRoom ( checkRoomId ) ;
if ( ! pR ) {
2016-03-08 08:35:07 +00:00
continue ;
}
2024-12-09 14:29:13 +00:00
if ( pR - > x ( ) = = x & & pR - > y ( ) = = y & & pR - > z ( ) = = z ) {
2017-06-26 16:46:54 +02:00
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
2017-06-26 16:46:54 +02:00
bool TMap : : gotoRoom ( int r )
2010-08-25 00:41:43 +02:00
{
mTargetID = r ;
2019-02-22 06:10:41 +00:00
return findPath ( mRoomIdHash . value ( mProfileName ) , r ) ;
2010-08-25 00:41:43 +02:00
}
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...
2017-06-26 16:46:54 +02:00
bool TMap : : gotoRoom ( int r1 , int r2 )
2010-08-25 00:41:43 +02:00
{
2017-06-26 16:46:54 +02:00
return findPath ( r1 , r2 ) ;
2010-08-25 00:41:43 +02:00
}
2025-11-19 02:57:25 +01: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 ) ;
}
}
2011-05-27 20:17:31 +02:00
void TMap : : initGraph ( )
2010-08-25 00:41:43 +02:00
{
2015-07-19 20:38:13 +01:00
QElapsedTimer _time ;
_time . start ( ) ;
2011-07-04 11:50:19 +02:00
locations . clear ( ) ;
2013-09-26 11:01:07 -04:00
roomidToIndex . clear ( ) ;
2011-07-04 11:50:19 +02:00
g . clear ( ) ;
2012-04-21 22:29:17 +02:00
g = mygraph_t ( ) ;
2017-06-26 16:46:54 +02:00
unsigned int roomCount = 0 ;
unsigned int edgeCount = 0 ;
2015-07-19 20:38:13 +01:00
QSet < unsigned int > unUsableRoomSet ;
2025-11-19 02:57:25 +01:00
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
2015-07-19 20:38:13 +01:00
// hopefully a MUCH smaller set in normal situations!
2017-06-26 16:46:54 +02:00
QHashIterator < int , TRoom * > itRoom = mpRoomDB - > getRoomMap ( ) ;
while ( itRoom . hasNext ( ) ) {
2015-07-19 20:38:13 +01:00
itRoom . next ( ) ;
2017-06-26 16:46:54 +02:00
TRoom * pR = itRoom . value ( ) ;
2025-11-19 02:57:25 +01:00
if ( itRoom . key ( ) < 1 | | ! pR ) {
2017-06-26 16:46:54 +02:00
unUsableRoomSet . insert ( itRoom . key ( ) ) ;
2011-05-27 20:17:31 +02:00
continue ;
}
2015-07-19 20:38:13 +01:00
2025-11-19 02:57:25 +01:00
if ( pR - > isLocked ) {
unUsableRoomSet . insert ( itRoom . key ( ) ) ;
if ( ! exitWeightFilterActive ) {
continue ;
}
}
2011-05-27 20:17:31 +02:00
location l ;
2015-07-19 20:38:13 +01:00
l . pR = pR ;
l . id = itRoom . key ( ) ;
2020-05-02 23:49:36 +01:00
// locations is std::vector<location> and (locations.at(k)).id will give room ID value
2017-06-26 16:46:54 +02:00
locations . push_back ( l ) ;
2020-11-05 10:56:26 +01:00
// This command maps usable TRooms (key) to index of entry in locations (for route finding).
// It loses invalid and unusable (i.e. locked) rooms
2017-06-26 16:46:54 +02:00
roomidToIndex . insert ( itRoom . key ( ) , roomCount + + ) ;
2013-09-26 11:01:07 -04:00
}
2015-07-19 20:38:13 +01:00
2025-11-19 02:57:25 +01:00
for ( unsigned int i = 0 ; i < roomCount ; + + i ) {
boost : : add_vertex ( g ) ;
}
2015-07-19 20:38:13 +01:00
// Now identify the routes between rooms, and pick out the best edges of parallel ones
2020-05-02 23:49:36 +01:00
for ( auto l : locations ) {
2023-05-14 15:06:15 +02:00
unsigned const int source = l . id ;
2017-06-26 16:46:54 +02:00
TRoom * pSourceR = l . pR ;
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,
2023-05-14 15:06:15 +02:00
QMap < QString , int > const exitWeights = pSourceR - > getExitWeights ( ) ;
2015-07-19 20:38:13 +01:00
2025-11-19 02:57:25 +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 ) ;
2015-07-19 20:38:13 +01:00
2020-12-31 22:06:00 +00:00
QMapIterator < QString , int > itSpecialExit ( pSourceR - > getSpecialExits ( ) ) ;
2017-06-26 16:46:54 +02:00
while ( itSpecialExit . hasNext ( ) ) {
2015-07-19 20:38:13 +01:00
itSpecialExit . next ( ) ;
2025-11-19 02:57:25 +01:00
addDirectionalRoute ( bestRoutes , exitWeights , source , pSourceR , itSpecialExit . value ( ) , DIR_OTHER , itSpecialExit . key ( ) , unUsableRoomSet ) ;
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
2015-07-19 20:38:13 +01:00
// insert the remainder into the BGL graph:
QHashIterator < unsigned int , route > itRoute = bestRoutes ;
2017-06-26 16:46:54 +02:00
while ( itRoute . hasNext ( ) ) {
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!
2017-06-26 16:46:54 +02:00
tie ( e , inserted ) = add_edge ( roomidToIndex . value ( source ) , roomidToIndex . value ( itRoute . key ( ) ) , itRoute . value ( ) . cost , g ) ;
edgeHash . insert ( qMakePair ( source , itRoute . key ( ) ) , itRoute . value ( ) ) ;
2015-07-19 20:38:13 +01:00
// The key is made from the QPair<edgeSourceRoomId, edgeTargetRoomId>...
edgeCount + + ;
2011-05-27 20:17:31 +02:00
}
2015-07-19 20:38:13 +01:00
} // End of foreach(location l, locations)
2012-05-15 23:16:58 +02:00
2011-05-27 20:17:31 +02:00
mMapGraphNeedsUpdate = false ;
2017-06-26 16:46:54 +02:00
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. " ;
2011-05-27 20:17:31 +02:00
}
2017-06-26 16:46:54 +02:00
bool TMap : : findPath ( int from , int to )
2011-05-27 20:17:31 +02:00
{
2017-06-26 16:46:54 +02:00
if ( mMapGraphNeedsUpdate ) {
2011-05-27 20:17:31 +02:00
initGraph ( ) ;
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!
2017-06-26 16:46:54 +02:00
if ( from = = to ) {
2021-08-22 08:01:05 +02:00
return true ; // Take a short-cut for trivial "already there" case!
2015-07-19 20:38:13 +01:00
}
2017-06-26 16:46:54 +02:00
TRoom * pFrom = mpRoomDB - > getRoom ( from ) ;
TRoom * pTo = mpRoomDB - > getRoom ( to ) ;
2015-07-19 20:38:13 +01:00
2017-06-26 16:46:54 +02:00
if ( ! pFrom | | ! pTo ) {
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 ;
2017-06-26 16:46:54 +02:00
if ( pFrom - > getNorth ( ) > 0 & & ( ! pFrom - > hasExitLock ( DIR_NORTH ) ) ) {
2015-07-19 20:38:13 +01:00
hasUsableExit = true ;
}
2017-06-26 16:46:54 +02:00
if ( ! hasUsableExit & & pFrom - > getSouth ( ) > 0 & & ( ! pFrom - > hasExitLock ( DIR_SOUTH ) ) ) {
2015-07-19 20:38:13 +01:00
hasUsableExit = true ;
}
2017-06-26 16:46:54 +02:00
if ( ! hasUsableExit & & pFrom - > getWest ( ) > 0 & & ( ! pFrom - > hasExitLock ( DIR_WEST ) ) ) {
2015-07-19 20:38:13 +01:00
hasUsableExit = true ;
}
2017-06-26 16:46:54 +02:00
if ( ! hasUsableExit & & pFrom - > getEast ( ) > 0 & & ( ! pFrom - > hasExitLock ( DIR_EAST ) ) ) {
2015-07-19 20:38:13 +01:00
hasUsableExit = true ;
}
2017-06-26 16:46:54 +02:00
if ( ! hasUsableExit & & pFrom - > getUp ( ) > 0 & & ( ! pFrom - > hasExitLock ( DIR_UP ) ) ) {
2015-07-19 20:38:13 +01:00
hasUsableExit = true ;
}
2017-06-26 16:46:54 +02:00
if ( ! hasUsableExit & & pFrom - > getDown ( ) > 0 & & ( ! pFrom - > hasExitLock ( DIR_DOWN ) ) ) {
2015-07-19 20:38:13 +01:00
hasUsableExit = true ;
}
2017-06-26 16:46:54 +02:00
if ( ! hasUsableExit & & pFrom - > getNortheast ( ) > 0 & & ( ! pFrom - > hasExitLock ( DIR_NORTHEAST ) ) ) {
2015-07-19 20:38:13 +01:00
hasUsableExit = true ;
}
2017-06-26 16:46:54 +02:00
if ( ! hasUsableExit & & pFrom - > getNorthwest ( ) > 0 & & ( ! pFrom - > hasExitLock ( DIR_NORTHWEST ) ) ) {
2015-07-19 20:38:13 +01:00
hasUsableExit = true ;
}
2017-06-26 16:46:54 +02:00
if ( ! hasUsableExit & & pFrom - > getSoutheast ( ) > 0 & & ( ! pFrom - > hasExitLock ( DIR_SOUTHEAST ) ) ) {
2015-07-19 20:38:13 +01:00
hasUsableExit = true ;
}
2017-06-26 16:46:54 +02:00
if ( ! hasUsableExit & & pFrom - > getSouthwest ( ) > 0 & & ( ! pFrom - > hasExitLock ( DIR_SOUTHWEST ) ) ) {
2015-07-19 20:38:13 +01:00
hasUsableExit = true ;
}
2017-06-26 16:46:54 +02:00
if ( ! hasUsableExit & & pFrom - > getIn ( ) > 0 & & ( ! pFrom - > hasExitLock ( DIR_IN ) ) ) {
2015-07-19 20:38:13 +01:00
hasUsableExit = true ;
}
2017-06-26 16:46:54 +02:00
if ( ! hasUsableExit & & pFrom - > getOut ( ) > 0 & & ( ! pFrom - > hasExitLock ( DIR_OUT ) ) ) {
2015-07-19 20:38:13 +01:00
hasUsableExit = true ;
}
2017-06-26 16:46:54 +02:00
if ( ! hasUsableExit ) {
2015-07-19 20:38:13 +01:00
// No available normal exits from this room so check the special ones
2020-12-31 22:06:00 +00:00
QStringList specialExitCommands = pFrom - > getSpecialExits ( ) . keys ( ) ;
2017-06-26 16:46:54 +02:00
while ( ! specialExitCommands . isEmpty ( ) ) {
2021-03-13 15:04:23 -05:00
if ( ! pFrom - > hasSpecialExitLock ( specialExitCommands . at ( 0 ) ) ) {
2015-07-19 20:38:13 +01:00
hasUsableExit = true ;
break ;
}
specialExitCommands . removeFirst ( ) ;
}
}
2017-06-26 16:46:54 +02:00
if ( ! hasUsableExit ) {
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!
}
2017-06-26 16:46:54 +02:00
if ( ! roomidToIndex . contains ( from ) ) {
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
}
2023-05-14 15:06:15 +02:00
vertex const start = roomidToIndex . value ( from ) ;
2015-07-19 20:38:13 +01:00
2017-06-26 16:46:54 +02:00
if ( ! roomidToIndex . contains ( to ) ) {
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
}
2023-05-14 15:06:15 +02:00
vertex const goal = roomidToIndex . value ( to ) ;
2015-07-19 20:38:13 +01:00
2025-11-19 02:57:25 +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 ...!
2025-11-19 02:57:25 +01:00
std : : vector < cost > d ( vertexCount ) ;
2015-07-19 20:38:13 +01:00
try {
2017-06-26 16:46:54 +02:00
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 & ) {
2020-10-30 07:53:18 +00:00
qDebug ( ) < < " TMap::findPath( " < < from < < " , " < < to < < " ) INFO: time elapsed in A*: " < < t . nsecsElapsed ( ) * 1.0e-6 < < " ms. " ;
2017-06-26 16:46:54 +02:00
t . restart ( ) ;
if ( ! roomidToIndex . contains ( to ) ) {
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 ] ;
2017-06-26 16:46:54 +02:00
if ( previousVertex = = currentVertex ) {
2020-10-30 07:53:18 +00:00
qDebug ( ) < < " TMap::findPath( " < < from < < " , " < < to < < " ) WARN: unable to build a path in: " < < t . nsecsElapsed ( ) * 1.0e-6 < < " ms. " ;
2015-07-19 20:38:13 +01:00
mPathList . clear ( ) ;
mDirList . clear ( ) ;
mWeightList . clear ( ) ; // Reset any partial results...
return false ;
}
2023-08-25 17:49:28 +01:00
const unsigned int previousRoomId = ( locations . at ( previousVertex ) ) . id ;
2023-05-14 15:06:15 +02:00
QPair < unsigned int , unsigned int > const edgeRoomIdPair = qMakePair ( previousRoomId , currentRoomId ) ;
2023-08-25 17:49:28 +01:00
const route r = edgeHash . value ( edgeRoomIdPair ) ;
2017-06-26 16:46:54 +02:00
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.} " ) ;
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
2020-05-02 23:49:36 +01:00
mWeightList . prepend ( r . cost ) ;
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! " ;
2015-07-19 20:38:13 +01:00
}
currentVertex = previousVertex ;
currentRoomId = previousRoomId ;
2017-06-26 16:46:54 +02:00
} while ( currentVertex ! = start ) ;
2015-07-19 20:38:13 +01:00
2020-10-30 07:53:18 +00:00
qDebug ( ) < < " TMap::findPath( " < < from < < " , " < < to < < " ) INFO: found path in: " < < t . nsecsElapsed ( ) * 1.0e-6 < < " ms. " ;
2015-07-19 20:38:13 +01:00
return true ;
}
2020-10-30 07:53:18 +00:00
qDebug ( ) < < " TMap::findPath( " < < from < < " , " < < to < < " ) INFO: did NOT find path in: " < < t . nsecsElapsed ( ) * 1.0e-6 < < " ms. " ;
2015-07-19 20:38:13 +01:00
return false ;
2010-08-25 00:41:43 +02:00
}
2019-01-11 10:07:29 +01: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 ) {
2023-11-27 00:15:47 +00:00
const QString errMsg = tr ( " [ ERROR ] - The format version \" %1 \" you are trying to save the map with is too new \n "
2021-04-19 08:07:25 +02:00
" for this version of Mudlet. Supported are only formats up to version %2. " )
2019-01-11 10:07:29 +01:00
. arg ( QString : : number ( saveVersion ) , QString : : number ( mMaxVersion ) ) ;
2019-01-12 20:56:31 +01:00
appendErrorMsgWithNoLf ( errMsg , false ) ;
2019-01-11 10:07:29 +01:00
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 ;
}
2019-01-11 10:07:29 +01:00
2019-01-16 23:23:34 +01:00
auto oldSaveVersion = mSaveVersion ;
// if 0 we default to current version selected
if ( saveVersion ! = 0 ) {
2019-01-11 10:07:29 +01:00
mSaveVersion = saveVersion ;
}
2017-06-26 16:46:54 +02:00
if ( mSaveVersion ! = mVersion ) {
2023-05-14 15:06:15 +02:00
const QString message = tr ( " [ ALERT ] - Saving map in format version \" %1 \" that is different than \" %2 \" which \n "
2021-04-19 08:07:25 +02:00
" it was loaded as. This may be an issue if you want to share the resulting \n "
2017-06-26 16:46:54 +02:00
" map with others relying on the original format. " )
. arg ( mSaveVersion )
. arg ( mVersion ) ;
appendErrorMsgWithNoLf ( message , false ) ;
mpHost - > mTelnet . postMessage ( message ) ;
}
if ( mSaveVersion ! = mDefaultVersion ) {
2023-05-14 15:06:15 +02:00
const QString message = tr ( " [ WARN ] - Saving map in format version \" %1 \" different from the \n "
2021-04-19 08:07:25 +02:00
" recommended map version %2 for this version of Mudlet. " )
2017-06-26 16:46:54 +02:00
. 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 ;
2019-05-28 03:43:50 -06:00
ofs < < mpRoomDB - > hashToRoomID ;
2019-08-16 22:07:07 +02:00
if ( mSaveVersion < 19 ) {
2026-08-05 06:41:14 +02:00
// 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 ;
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 ;
2016-03-05 06:48:08 +00:00
}
2012-05-15 23:16:58 +02:00
2023-11-27 00:15:47 +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 ( ) ) ;
2012-05-15 23:16:58 +02:00
// serialize area table
2017-06-26 16:46:54 +02:00
QMapIterator < int , TArea * > itAreaList ( mpRoomDB - > getAreaMap ( ) ) ;
while ( itAreaList . hasNext ( ) ) {
2012-05-15 23:16:58 +02:00
itAreaList . next ( ) ;
2023-05-14 15:06:15 +02:00
const int areaID = itAreaList . key ( ) ;
2017-06-26 16:46:54 +02:00
TArea * pA = itAreaList . value ( ) ;
2012-05-15 23:16:58 +02:00
ofs < < areaID ;
2017-06-26 16:46:54 +02:00
if ( mSaveVersion > = 18 ) {
2016-03-05 18:47:27 +00:00
ofs < < pA - > rooms ;
2017-06-26 16:46:54 +02:00
} else {
2016-03-05 18:47:27 +00:00
// Switched to a (faster) QSet<int> from a QList<int> in version 18
2023-05-14 15:06:15 +02:00
QList < int > const _oldList = pA - > rooms . values ( ) ;
2016-03-05 18:47:27 +00:00
ofs < < _oldList ;
}
2018-08-22 07:59:43 +02:00
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 ;
2012-05-15 23:16:58 +02:00
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 ;
2019-08-16 22:07:07 +02:00
ofs < < pA - > xmaxForZ ;
ofs < < pA - > ymaxForZ ;
ofs < < pA - > xminForZ ;
ofs < < pA - > yminForZ ;
2012-05-15 23:16:58 +02:00
ofs < < pA - > pos ;
ofs < < pA - > isZone ;
ofs < < pA - > zoneAreaRef ;
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 ( ) ) ) ;
}
2026-02-04 08:30:01 +01:00
// Store font and outline color info for labels in userData (avoids binary format version change)
2026-01-19 07:31:50 +01:00
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 ) ;
}
2026-02-04 08:30:01 +01:00
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 ) ;
2026-01-19 07:31:50 +01:00
}
2019-08-16 22:07:07 +02:00
ofs < < pA - > mUserData ;
2021-01-17 09:02:23 +00:00
if ( mSaveVersion > = 21 ) {
// Revised in version 21 to store labels within the TArea class:
2022-11-11 05:01:28 +00:00
// Also we now have temporary labels, so we need to count the
// permanent ones first to use as the count for ones to store:
2023-11-27 00:15:47 +00:00
ofs < < static_cast < qint32 > ( permanentLabelsList . size ( ) ) ;
2022-11-11 05:01:28 +00:00
QListIterator < int > itMapLabelId ( permanentLabelsList ) ;
while ( itMapLabelId . hasNext ( ) ) {
const auto labelID = itMapLabelId . next ( ) ;
const auto label = pA - > mMapLabels . value ( labelID ) ;
ofs < < labelID ;
2021-01-27 08:32:33 +00:00
ofs < < label . pos ;
2021-01-17 09:02:23 +00:00
ofs < < label . size ;
ofs < < label . text ;
ofs < < label . fgColor ;
ofs < < label . bgColor ;
ofs < < label . pix ;
ofs < < label . noScaling ;
ofs < < label . showOnTop ;
}
}
2016-03-05 06:48:08 +00:00
}
2017-06-26 16:46:54 +02:00
if ( mSaveVersion > = 18 ) {
2016-03-05 18:47:27 +00:00
// 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 ;
2017-06-26 16:46:54 +02:00
} else {
2019-02-22 06:10:41 +00:00
ofs < < mRoomIdHash . value ( mProfileName ) ;
2016-03-05 18:47:27 +00: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
2021-01-17 09:02:23 +00:00
if ( mSaveVersion < 21 ) {
// Before version 21 the map labels were stored within this class:
2022-11-11 05:01:28 +00:00
// 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 ;
2021-01-17 09:02:23 +00:00
// Need to count the areas that have mapLabels:
QMapIterator < int , TArea * > itArea ( mpRoomDB - > getAreaMap ( ) ) ;
2022-11-11 05:01:28 +00:00
while ( itArea . hasNext ( ) ) {
// Now we have temporary labels we need to identify areas with
// permanent ones:
2021-01-17 09:02:23 +00:00
itArea . next ( ) ;
auto pArea = itArea . value ( ) ;
2022-11-11 05:01:28 +00:00
if ( pArea & & ! pArea - > mMapLabels . isEmpty ( ) & & pArea - > hasPermanentLabels ( ) ) {
areasWithPermanentLabels . insert ( itArea . key ( ) , itArea . value ( ) ) ;
2021-01-17 09:02:23 +00:00
}
2022-11-11 05:01:28 +00:00
}
2023-11-27 00:15:47 +00:00
ofs < < static_cast < qint32 > ( areasWithPermanentLabels . count ( ) ) ;
2022-11-11 05:01:28 +00:00
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:
2023-11-27 00:15:47 +00:00
ofs < < static_cast < qint32 > ( permanentLabelIdsList . size ( ) ) ;
2021-01-17 09:02:23 +00:00
// only used to assign labels to the area:
2022-11-11 05:01:28 +00:00
ofs < < itAreaWithLabels . key ( ) ;
QListIterator < int > itPerminentMapLabelIds ( permanentLabelIdsList ) ;
while ( itPerminentMapLabelIds . hasNext ( ) ) {
auto labelID = itPerminentMapLabelIds . next ( ) ;
ofs < < labelID ; //label ID
2023-05-14 15:06:15 +02:00
TMapLabel const label = pArea - > mMapLabels . value ( labelID ) ;
2021-01-27 08:32:33 +00:00
ofs < < label . pos ;
2021-01-17 09:02:23 +00:00
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 ;
2020-12-28 06:34:18 +00:00
}
2011-06-26 23:26:24 +02:00
}
}
2021-01-17 09:02:23 +00:00
2017-06-26 16:46:54 +02:00
QHashIterator < int , TRoom * > it ( mpRoomDB - > getRoomMap ( ) ) ;
while ( it . hasNext ( ) ) {
2010-08-25 00:41:43 +02:00
it . next ( ) ;
2017-06-26 16:46:54 +02:00
TRoom * pR = it . value ( ) ;
if ( ! pR ) {
qDebug ( ) < < " TMap::serialize(...) skipping a room with a NULL TRoom pointer: " < < it . key ( ) ;
2016-03-05 06:48:08 +00:00
continue ;
}
ofs < < pR - > getId ( ) ;
2013-03-22 12:47:58 +01:00
ofs < < pR - > getArea ( ) ;
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 ;
2020-12-31 22:06:00 +00:00
if ( mSaveVersion > = 21 ) {
2026-04-04 07:18:03 +01:00
ofs < < pR - > hidden ;
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 ;
2026-04-26 20:05:35 +01:00
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
2024-03-11 15:40:56 +00:00
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
2021-01-05 16:14:41 +01: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 ) ;
}
2026-08-05 06:41:14 +02:00
// 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 ;
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 ( ) ;
2023-05-14 15:06:15 +02:00
const QString direction ( itCustomLine . key ( ) ) ;
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 ( ) ;
2023-05-14 15:06:15 +02:00
const QString direction ( itCustomLineArrow . key ( ) ) ;
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 ) ;
2019-05-23 01:45:14 +01:00
while ( itCustomLineColor . hasNext ( ) ) {
2018-11-17 20:46:02 +00:00
itCustomLineColor . next ( ) ;
2023-05-14 15:06:15 +02:00
const QString direction ( itCustomLineColor . key ( ) ) ;
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 :
2019-07-26 03:03:47 +02:00
[[fallthrough]] ;
2018-11-17 20:46:02 +00:00
default :
oldLineStyleData . insert ( direction , QLatin1String ( " solid line " ) ) ;
}
}
ofs < < oldLineStyleData ;
}
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
}
2019-01-11 10:07:29 +01:00
2019-01-16 23:23:34 +01: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 ) ) {
2023-05-14 15:06:15 +02:00
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 ) ) {
2023-05-14 15:06:15 +02:00
const QString errMsg = tr ( " [ ALERT ] - File does not seem to be a Mudlet Map file. The part that indicates \n "
2021-04-19 08:07:25 +02:00
" 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 ) ;
2023-05-14 15:06:15 +02:00
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 ) {
2023-05-14 15:06:15 +02:00
const QString errMsg = tr ( " [ ALERT ] - Map file is too new. Its format version \" %1 \" is higher than this version of \n "
2021-04-19 08:07:25 +02:00
" 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 ) ;
2023-05-14 15:06:15 +02:00
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 ) {
2023-05-14 15:06:15 +02:00
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 "
2021-04-19 08:07:25 +02:00
" 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 ) ;
2023-05-14 15:06:15 +02:00
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
2023-05-14 15:06:15 +02:00
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 ( ) ) ;
2021-04-19 08:07:25 +02:00
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 ;
}
2026-04-25 13:02:24 +02:00
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 ( ) ;
2011-10-11 04:09:28 +02:00
QString folder ;
QStringList entries ;
2017-06-26 16:46:54 +02:00
if ( location . isEmpty ( ) ) {
2025-01-08 10:04:50 +01:00
folder = mudlet : : getMudletPath ( enums : : profileMapsPath , mProfileName ) ;
2023-05-14 15:06:15 +02:00
const QDir dir ( folder ) ;
2021-04-02 19:10:16 +01:00
QStringList filters ;
2021-12-07 06:21:39 +01:00
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 ) ;
2011-10-11 04:09:28 +02:00
}
2010-08-25 00:41:43 +02:00
bool canRestore = true ;
2021-05-21 16:45:17 +02:00
if ( entries . empty ( ) & & location . isEmpty ( ) ) {
canRestore = false ;
}
2021-04-02 19:10:16 +01:00
QDataStream ifs ;
QFile file ;
2021-05-21 16:45:17 +02:00
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 ) ;
2021-12-07 06:21:39 +01:00
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
2023-05-14 15:06:15 +02:00
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 ) ;
2023-05-14 15:06:15 +02:00
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 ;
}
}
2026-01-19 18:10:44 +01:00
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 ;
}
2021-05-21 16:45:17 +02:00
} 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
2017-06-26 16:46:54 +02:00
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
}
2017-06-26 16:46:54 +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
}
2017-06-26 16:46:54 +02:00
if ( mVersion > = 7 ) {
2019-05-28 03:43:50 -06:00
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
2017-06-26 16:46:54 +02: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 ) {
2020-12-30 19:36:26 +00:00
// 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 ( " , " ) ) ) ;
2020-12-30 19:36:26 +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
ifs > > mMapSymbolFontFudgeFactor ;
ifs > > mIsOnlyMapSymbolFontToBeUsed ;
2026-08-05 06:41:14 +02:00
// 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:
2020-12-30 19:36:26 +00:00
// 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:
2023-05-14 15:06:15 +02:00
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 ( ) ) {
2020-12-30 19:36:26 +00:00
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
2020-05-02 23:49:36 +01:00
mMapSymbolFont . setStyleStrategy ( static_cast < QFont : : StyleStrategy > ( ( mIsOnlyMapSymbolFontToBeUsed ? QFont : : NoFontMerging : 0 ) | QFont : : PreferOutline | QFont : : PreferAntialias
| QFont : : PreferQuality | QFont : : PreferNoShaping ) ) ;
2017-06-26 16:46:54 +02:00
if ( mVersion > = 14 ) {
2021-04-02 19:10:16 +01:00
int areaSize = 0 ;
2012-05-15 23:16:58 +02:00
ifs > > areaSize ;
// restore area table
2017-06-26 16:46:54 +02:00
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 ;
2012-05-15 23:16:58 +02:00
ifs > > areaID ;
2017-06-26 16:46:54 +02:00
if ( mVersion > = 18 ) {
2016-03-05 18:47:27 +00:00
// 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 ;
2017-06-26 16:46:54 +02:00
} else {
2016-03-05 18:47:27 +00:00
QList < int > oldRoomsList ;
ifs > > oldRoomsList ;
2020-05-01 06:06:08 +01:00
pA - > rooms = QSet < int > { oldRoomsList . begin ( ) , oldRoomsList . end ( ) } ;
2015-07-19 20:38:13 +01:00
}
2017-06-26 16:46:54 +02:00
// Can be useful when analysing suspect map files!
// qDebug() << "TMap::restore(...)" << "Area:" << areaID;
// qDebug() << "Rooms:" << pA->rooms;
2018-08-22 07:59:43 +02:00
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 ;
2012-05-15 23:16:58 +02:00
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 ;
2017-06-26 16:46:54 +02:00
if ( mVersion > = 17 ) {
2019-05-25 04:21:39 -06:00
ifs > > pA - > xmaxForZ ;
ifs > > pA - > ymaxForZ ;
ifs > > pA - > xminForZ ;
ifs > > pA - > yminForZ ;
2017-06-26 16:46:54 +02:00
} else {
2019-05-25 04:21:39 -06:00
QMap < int , int > dummyMinMaxForZ ;
ifs > > pA - > xmaxForZ ;
ifs > > pA - > ymaxForZ ;
ifs > > dummyMinMaxForZ ;
ifs > > pA - > xminForZ ;
ifs > > pA - > yminForZ ;
ifs > > dummyMinMaxForZ ;
2016-03-08 08:35:07 +00:00
}
2012-05-15 23:16:58 +02:00
ifs > > pA - > pos ;
ifs > > pA - > isZone ;
ifs > > pA - > zoneAreaRef ;
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 ;
2024-03-11 15:40:56 +00:00
const qreal fallback_map2DZoom = pA - > mUserData . take ( QLatin1String ( " system.fallback_map2DZoom " ) ) . toDouble ( ) ;
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
}
2021-01-17 09:02:23 +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 ;
2021-01-17 09:02:23 +00:00
ifs > > label . size ;
ifs > > label . text ;
ifs > > label . fgColor ;
ifs > > label . bgColor ;
ifs > > label . pix ;
ifs > > label . noScaling ;
ifs > > label . showOnTop ;
2026-01-19 07:31:50 +01:00
restoreLabelFontFromUserData ( label , labelId , pA - > mUserData ) ;
2026-02-04 08:30:01 +01:00
restoreLabelOutlineColorFromUserData ( label , labelId , pA - > mUserData ) ;
2021-01-17 09:02:23 +00:00
pA - > mMapLabels . insert ( labelId , label ) ;
}
}
2017-06-26 16:46:54 +02:00
mpRoomDB - > restoreSingleArea ( areaID , pA ) ;
2012-05-15 23:16:58 +02:00
}
}
2017-06-26 16:46:54 +02:00
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 ( ) ) ;
2017-06-26 16:46:54 +02:00
mpRoomDB - > restoreSingleArea ( - 1 , pDefaultA ) ;
2023-05-14 15:06:15 +02:00
const QString defaultAreaInsertionMsg = tr ( " [ INFO ] - Default (reset) area (for rooms that have not been assigned to an \n "
2017-06-26 16:46:54 +02:00
" area) not found, adding reserved -1 id. " ) ;
appendErrorMsgWithNoLf ( defaultAreaInsertionMsg , false ) ;
if ( mudlet : : self ( ) - > showMapAuditErrors ( ) ) {
postMessage ( defaultAreaInsertionMsg ) ;
2012-05-15 23:16:58 +02:00
}
}
2017-06-26 16:46:54 +02:00
if ( mVersion > = 18 ) {
2016-03-05 18:47:27 +00:00
// 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 ;
2017-06-26 16:46:54 +02:00
} else if ( mVersion > = 12 ) {
2021-04-02 19:10:16 +01:00
int oldRoomId = 0 ;
2016-03-05 18:47:27 +00:00
ifs > > oldRoomId ;
2019-02-22 06:10:41 +00:00
mRoomIdHash [ mProfileName ] = oldRoomId ;
2011-10-11 04:09:28 +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
2021-01-17 09:02:23 +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 ;
2021-01-17 09:02:23 +00:00
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 ;
2017-06-26 16:46:54 +02:00
if ( mVersion > = 12 ) {
2021-01-17 09:02:23 +00:00
// From version 12 labels could be placed on any level,
// so they have a z coordinate:
2011-10-30 02:57:50 +02:00
ifs > > label . pos ;
2017-06-26 16:46:54 +02:00
} else {
2021-01-17 09:02:23 +00:00
QPointF labelPos2D ;
ifs > > labelPos2D ;
label . pos = QVector3D ( labelPos2D ) ;
2020-12-28 06:34:18 +00:00
}
2021-01-17 09:02:23 +00:00
// 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 ;
2017-06-26 16:46:54 +02:00
if ( mVersion > = 15 ) {
2012-12-29 02:16:28 +01:00
ifs > > label . noScaling ;
ifs > > label . showOnTop ;
}
2021-01-17 09:02:23 +00:00
if ( pA ) {
2026-01-19 07:31:50 +01:00
restoreLabelFontFromUserData ( label , labelID , pA - > mUserData ) ;
2026-02-04 08:30:01 +01:00
restoreLabelOutlineColorFromUserData ( label , labelID , pA - > mUserData ) ;
2021-01-17 09:02:23 +00:00
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
}
2021-01-17 09:02:23 +00: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
2017-06-26 16:46:54 +02: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 ( ) ) ;
2017-06-26 16:46:54 +02:00
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
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
2026-01-25 12:19:45 +01: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 ( ) ;
}
}
2023-05-14 15:06:15 +02:00
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 ) ;
2016-05-03 04:58:31 +01:00
2017-06-26 16:46:54 +02: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
2017-06-26 16:46:54 +02:00
return canRestore ; //FIXME
2010-08-25 00:41:43 +02:00
}
2016-03-05 18:47:27 +00: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
2023-11-27 00:15:47 +00:00
// copied across (if the room STILL exists)! This is to avoid a replacement map
2016-03-05 18:47:27 +00:00
// (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...!
2023-11-27 00:15:47 +00:00
bool TMap : : retrieveMapFileStats ( QString profile , QString * latestFileName = nullptr , int * fileVersion = nullptr , int * roomId = nullptr , qsizetype * areaCount = nullptr , qsizetype * roomCount = nullptr )
2016-03-05 18:47:27 +00:00
{
2017-06-26 16:46:54 +02:00
if ( profile . isEmpty ( ) ) {
2016-03-05 18:47:27 +00:00
return false ;
}
QString folder ;
QStringList entries ;
2025-01-08 10:04:50 +01:00
folder = mudlet : : getMudletPath ( enums : : profileMapsPath , profile ) ;
2017-06-26 16:46:54 +02:00
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 ) ;
2017-06-26 16:46:54 +02:00
if ( entries . isEmpty ( ) ) {
2017-04-08 08:44:35 +02:00
return false ;
}
2016-03-05 18:47:27 +00:00
// As the files are sorted by time this gets the latest one
2021-12-07 06:21:39 +01:00
QFile file ( qsl ( " %1/%2 " ) . arg ( folder , entries . at ( 0 ) ) ) ;
2016-03-05 18:47:27 +00:00
2017-06-26 16:46:54 +02:00
if ( ! file . open ( QFile : : ReadOnly ) ) {
2023-05-14 15:06:15 +02:00
const QString errMsg = tr ( R " ([ ERROR ] - Unable to open map file for reading: " % 1 " !) " ) . arg ( file . fileName ( ) ) ;
2017-06-26 16:46:54 +02:00
appendErrorMsg ( errMsg , false ) ;
postMessage ( errMsg ) ;
2016-03-05 18:47:27 +00:00
return false ;
}
2017-06-26 16:46:54 +02:00
if ( latestFileName ) {
2016-03-05 18:47:27 +00:00
* latestFileName = file . fileName ( ) ;
}
int otherProfileVersion = 0 ;
2017-06-26 16:46:54 +02:00
QDataStream ifs ( & file ) ;
2019-09-29 23:41:58 +02:00
if ( mudlet : : scmRunTimeQtVersion > = QVersionNumber ( 5 , 13 , 0 ) ) {
ifs . setVersion ( mudlet : : scmQDataStreamFormat_5_12 ) ;
}
2016-03-05 18:47:27 +00:00
ifs > > otherProfileVersion ;
2023-05-14 15:06:15 +02:00
const QString infoMsg = tr ( R " ([ INFO ] - Checking map file " % 1 " , format version " % 2 " .) " ) . arg ( file . fileName ( ) ) . arg ( otherProfileVersion ) ;
2017-06-26 16:46:54 +02:00
appendErrorMsg ( infoMsg , false ) ;
if ( mudlet : : self ( ) - > showMapAuditErrors ( ) ) {
postMessage ( infoMsg ) ;
2016-05-03 04:58:31 +01:00
}
2016-03-05 18:47:27 +00:00
2017-06-26 16:46:54 +02:00
if ( otherProfileVersion > mDefaultVersion ) {
2024-01-20 18:53:36 +01:00
if ( mudlet : : self ( ) - > releaseVersion | | mudlet : : self ( ) - > publicTestVersion ) {
2019-10-19 16:45:38 +02:00
// This is a release/public test version - should not support any map file versions higher that it was built for
2017-06-26 16:46:54 +02:00
if ( fileVersion ) {
* fileVersion = otherProfileVersion ;
2016-03-05 18:47:27 +00:00
}
file . close ( ) ;
return true ;
2026-07-18 18:39:57 +02:00
}
// Is a development version so check against mMaxVersion
if ( otherProfileVersion > mMaxVersion ) {
// Oh dear, can't handle THIS
if ( fileVersion ) {
* fileVersion = otherProfileVersion ;
2016-03-05 18:47:27 +00:00
}
2026-07-18 18:39:57 +02:00
file . close ( ) ;
return true ;
}
if ( fileVersion ) {
* fileVersion = otherProfileVersion ;
2016-03-05 18:47:27 +00:00
}
2026-07-18 18:39:57 +02:00
2017-06-26 16:46:54 +02:00
} else {
if ( fileVersion ) {
* fileVersion = otherProfileVersion ;
2016-03-05 18:47:27 +00:00
}
}
2017-06-26 16:46:54 +02:00
if ( otherProfileVersion > = 4 ) {
2016-03-05 18:47:27 +00:00
// envColorMap
QMap < int , int > _dummyQMapIntInt ;
ifs > > _dummyQMapIntInt ;
// AreaNamesMap
QMap < int , QString > _dummyQMapIntQString ;
ifs > > _dummyQMapIntQString ;
}
2017-06-26 16:46:54 +02:00
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
2016-03-05 18:47:27 +00:00
QMap < int , QColor > _dummyQMapIntQColor ;
ifs > > _dummyQMapIntQColor ;
}
2017-06-26 16:46:54 +02:00
if ( otherProfileVersion > = 7 ) {
2019-05-28 03:43:50 -06:00
// hashToRoomID
QMap < QString , int > _dummyQMapQStringInt ;
ifs > > _dummyQMapQStringInt ;
2016-03-05 18:47:27 +00:00
}
2017-06-26 16:46:54 +02:00
if ( otherProfileVersion > = 17 ) {
2016-03-05 18:47:27 +00:00
// 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 ;
}
2016-03-05 18:47:27 +00:00
}
2017-06-26 16:46:54 +02:00
if ( otherProfileVersion > = 14 ) {
2023-11-27 00:15:47 +00:00
int readAreaSize ;
ifs > > readAreaSize ;
qsizetype areaSize = static_cast < qsizetype > ( readAreaSize ) ;
2017-06-26 16:46:54 +02:00
if ( areaCount ) {
* areaCount = areaSize ;
2016-03-05 18:47:27 +00:00
}
// read each area
2023-11-27 00:15:47 +00:00
for ( qsizetype i = 0 ; i < areaSize ; + + i ) {
2017-08-03 08:46:00 +02:00
TArea pA ( nullptr , nullptr ) ;
2016-03-05 18:47:27 +00:00
int areaID ;
ifs > > areaID ;
2017-04-09 07:03:25 +02:00
ifs > > pA . rooms ;
2018-08-22 07:59:43 +02:00
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 ;
2017-04-09 07:03:25 +02:00
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 ;
2017-06-26 16:46:54 +02:00
if ( otherProfileVersion > = 17 ) {
2019-05-25 04:21:39 -06:00
ifs > > pA . xmaxForZ ;
ifs > > pA . ymaxForZ ;
ifs > > pA . xminForZ ;
ifs > > pA . yminForZ ;
2017-06-26 16:46:54 +02:00
} else {
2019-05-25 04:21:39 -06:00
QMap < int , int > dummyMinMaxForZ ;
ifs > > pA . xmaxForZ ;
ifs > > pA . ymaxForZ ;
ifs > > dummyMinMaxForZ ;
ifs > > pA . xminForZ ;
ifs > > pA . yminForZ ;
ifs > > dummyMinMaxForZ ;
2016-03-05 18:47:27 +00:00
}
2017-04-09 07:03:25 +02:00
ifs > > pA . pos ;
ifs > > pA . isZone ;
ifs > > pA . zoneAreaRef ;
2023-03-16 15:00:33 +00:00
if ( otherProfileVersion > = 21 ) {
ifs > > pA . mLast2DMapZoom ;
}
2017-06-26 16:46:54 +02:00
if ( otherProfileVersion > = 17 ) {
2017-04-09 07:03:25 +02:00
ifs > > pA . mUserData ;
2016-03-05 18:47:27 +00:00
}
2021-01-17 09:02:23 +00:00
if ( otherProfileVersion > = 21 ) {
int mapLabelsCount = - 1 ;
ifs > > mapLabelsCount ;
for ( int i = 0 ; i < mapLabelsCount ; + + i ) {
int labelId = - 1 ;
ifs > > labelId ;
TMapLabel label ;
2021-01-27 08:32:33 +00:00
ifs > > label . pos ;
2021-01-17 09:02:23 +00:00
ifs > > label . size ;
ifs > > label . text ;
ifs > > label . fgColor ;
ifs > > label . bgColor ;
ifs > > label . pix ;
ifs > > label . noScaling ;
ifs > > label . showOnTop ;
}
}
2016-03-05 18:47:27 +00:00
}
}
2017-06-26 16:46:54 +02:00
if ( otherProfileVersion > = 18 ) {
2016-03-05 18:47:27 +00:00
// 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 ;
2017-06-26 16:46:54 +02:00
if ( roomId ) {
* roomId = _dummyQHashQStringInt . value ( profile ) ;
2016-03-05 18:47:27 +00:00
}
2017-06-26 16:46:54 +02:00
} else if ( otherProfileVersion > = 12 ) {
2016-03-05 18:47:27 +00:00
int oldRoomId ;
ifs > > oldRoomId ;
2017-06-26 16:46:54 +02:00
if ( roomId ) {
* roomId = oldRoomId ;
2016-03-05 18:47:27 +00:00
}
2017-06-26 16:46:54 +02:00
} else {
if ( roomId ) {
* roomId = - 1 ; // Not found value
2016-03-05 18:47:27 +00:00
}
}
2021-01-17 09:02:23 +00:00
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 ;
2016-03-05 18:47:27 +00:00
ifs > > areaID ;
2021-01-17 09:02:23 +00:00
int areaLabelCounter = 0 ;
while ( ! ifs . atEnd ( ) & & areaLabelCounter < areaLabelsTotal ) {
2016-03-05 18:47:27 +00:00
int labelID ;
ifs > > labelID ;
TMapLabel label ;
2017-06-26 16:46:54 +02:00
if ( otherProfileVersion > = 12 ) {
2016-03-05 18:47:27 +00:00
ifs > > label . pos ;
2017-06-26 16:46:54 +02:00
} else {
2021-01-27 08:32:33 +00:00
QPointF oldLabelPos ;
ifs > > oldLabelPos ;
label . pos = QVector3D ( oldLabelPos ) ;
2016-03-05 18:47:27 +00:00
}
2021-01-17 09:02:23 +00:00
QPointF dummyPointF ;
ifs > > dummyPointF ;
2016-03-05 18:47:27 +00:00
ifs > > label . size ;
ifs > > label . text ;
ifs > > label . fgColor ;
ifs > > label . bgColor ;
ifs > > label . pix ;
2017-06-26 16:46:54 +02:00
if ( otherProfileVersion > = 15 ) {
2016-03-05 18:47:27 +00:00
ifs > > label . noScaling ;
ifs > > label . showOnTop ;
}
2021-01-17 09:02:23 +00:00
+ + areaLabelCounter ;
2016-03-05 18:47:27 +00:00
}
2021-01-17 09:02:23 +00:00
+ + areasWithLabelsCounter ;
2016-03-05 18:47:27 +00:00
}
}
2017-08-03 08:46:00 +02:00
TRoom _pT ( nullptr ) ;
2016-03-05 18:47:27 +00:00
QSet < int > _dummyRoomIdSet ;
2017-06-26 16:46:54 +02:00
while ( ! ifs . atEnd ( ) ) {
2016-03-05 18:47:27 +00:00
int i ;
ifs > > i ;
2017-06-26 16:46:54 +02:00
_pT . restore ( ifs , i , otherProfileVersion ) ;
2016-03-05 18:47:27 +00:00
// Can't do mpRoomDB->restoreSingleRoom( ifs, i, pT ) as it would mess up
// this TMap::mpRoomDB
// So emulate using _dummyRoomIdSet
2017-06-26 16:46:54 +02:00
if ( i > 0 & & ! _dummyRoomIdSet . contains ( i ) ) {
_dummyRoomIdSet . insert ( i ) ;
2016-03-05 18:47:27 +00:00
}
}
2017-06-26 16:46:54 +02:00
if ( roomCount ) {
2016-03-05 18:47:27 +00:00
* roomCount = _dummyRoomIdSet . count ( ) ;
}
return true ;
}
2010-08-25 00:41:43 +02:00
2021-09-03 10:47:43 +02:00
//NOLINT(readability-make-member-function-const)
Add: give map label text the ability to have an outline (#7598)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Add an outline colour chooser to map label creation window in mapper.
Update createMapLabel Lua function to reflect this as well. Adds three
optional arguments to the end of createMapLabel( ..., outlineRed,
outlineGreen, outlineBlue), default to the same colour as foreground if
not specified.
Also, chosen colours weren't being saved from one dialog to the next
forcing unnecessary typing to replicate a colour scheme when creating
multiple labels, so fix this and allow chosen colours to also save
across Mudlet restarts as well.
#### Motivation for adding to Mudlet
Better user experience, more map design options, prettier maps.
#### Other info (issues closed, discussion etc)
- The outline width is only 1 pixel, but as fonts get smaller this
starts to become increasingly larger compared to the width of the small
font. Zoomed in fonts (or larger than 16 on my display) typically look
better.
- Based on this work I think it would be fairly trivial to add drop
shadows, mirroring and other text effects.

Zoomed in;

closes #2861
/claim #2861
2024-12-27 12:07:37 +04:00
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
{
2021-01-17 09:02:23 +00:00
auto pA = mpRoomDB - > getArea ( area ) ;
if ( ! pA ) {
return - 1 ;
}
if ( text . isEmpty ( ) ) {
2017-06-26 16:46:54 +02:00
return - 1 ;
}
2012-12-28 16:09:59 +01:00
2011-06-26 15:23:37 +02:00
TMapLabel label ;
label . text = text ;
label . bgColor = bg ;
label . fgColor = fg ;
Add: give map label text the ability to have an outline (#7598)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Add an outline colour chooser to map label creation window in mapper.
Update createMapLabel Lua function to reflect this as well. Adds three
optional arguments to the end of createMapLabel( ..., outlineRed,
outlineGreen, outlineBlue), default to the same colour as foreground if
not specified.
Also, chosen colours weren't being saved from one dialog to the next
forcing unnecessary typing to replicate a colour scheme when creating
multiple labels, so fix this and allow chosen colours to also save
across Mudlet restarts as well.
#### Motivation for adding to Mudlet
Better user experience, more map design options, prettier maps.
#### Other info (issues closed, discussion etc)
- The outline width is only 1 pixel, but as fonts get smaller this
starts to become increasingly larger compared to the width of the small
font. Zoomed in fonts (or larger than 16 on my display) typically look
better.
- Based on this work I think it would be fairly trivial to add drop
shadows, mirroring and other text effects.

Zoomed in;

closes #2861
/claim #2861
2024-12-27 12:07:37 +04:00
label . outlineColor = outline ;
2017-06-26 16:46:54 +02:00
label . size = QSizeF ( 100 , 100 ) ;
label . pos = QVector3D ( x , y , z ) ;
2012-12-28 16:09:59 +01:00
label . showOnTop = showOnTop ;
label . noScaling = noScaling ;
2022-11-11 05:01:28 +00:00
label . temporary = temporary ;
2012-12-28 16:09:59 +01:00
Add: give map label text the ability to have an outline (#7598)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Add an outline colour chooser to map label creation window in mapper.
Update createMapLabel Lua function to reflect this as well. Adds three
optional arguments to the end of createMapLabel( ..., outlineRed,
outlineGreen, outlineBlue), default to the same colour as foreground if
not specified.
Also, chosen colours weren't being saved from one dialog to the next
forcing unnecessary typing to replicate a colour scheme when creating
multiple labels, so fix this and allow chosen colours to also save
across Mudlet restarts as well.
#### Motivation for adding to Mudlet
Better user experience, more map design options, prettier maps.
#### Other info (issues closed, discussion etc)
- The outline width is only 1 pixel, but as fonts get smaller this
starts to become increasingly larger compared to the width of the small
font. Zoomed in fonts (or larger than 16 on my display) typically look
better.
- Based on this work I think it would be fairly trivial to add drop
shadows, mirroring and other text effects.

Zoomed in;

closes #2861
/claim #2861
2024-12-27 12:07:37 +04:00
const QRectF lr = QRectF ( 0 , 0 , 2000 , 2000 ) ;
2017-06-26 16:46:54 +02:00
QPixmap pix ( lr . size ( ) . toSize ( ) ) ;
2017-04-29 10:42:28 +02:00
pix . fill ( Qt : : transparent ) ;
Add: give map label text the ability to have an outline (#7598)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Add an outline colour chooser to map label creation window in mapper.
Update createMapLabel Lua function to reflect this as well. Adds three
optional arguments to the end of createMapLabel( ..., outlineRed,
outlineGreen, outlineBlue), default to the same colour as foreground if
not specified.
Also, chosen colours weren't being saved from one dialog to the next
forcing unnecessary typing to replicate a colour scheme when creating
multiple labels, so fix this and allow chosen colours to also save
across Mudlet restarts as well.
#### Motivation for adding to Mudlet
Better user experience, more map design options, prettier maps.
#### Other info (issues closed, discussion etc)
- The outline width is only 1 pixel, but as fonts get smaller this
starts to become increasingly larger compared to the width of the small
font. Zoomed in fonts (or larger than 16 on my display) typically look
better.
- Based on this work I think it would be fairly trivial to add drop
shadows, mirroring and other text effects.

Zoomed in;

closes #2861
/claim #2861
2024-12-27 12:07:37 +04:00
2017-06-26 16:46:54 +02:00
QPainter lp ( & pix ) ;
lp . fillRect ( lr , label . bgColor ) ;
Add: give map label text the ability to have an outline (#7598)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Add an outline colour chooser to map label creation window in mapper.
Update createMapLabel Lua function to reflect this as well. Adds three
optional arguments to the end of createMapLabel( ..., outlineRed,
outlineGreen, outlineBlue), default to the same colour as foreground if
not specified.
Also, chosen colours weren't being saved from one dialog to the next
forcing unnecessary typing to replicate a colour scheme when creating
multiple labels, so fix this and allow chosen colours to also save
across Mudlet restarts as well.
#### Motivation for adding to Mudlet
Better user experience, more map design options, prettier maps.
#### Other info (issues closed, discussion etc)
- The outline width is only 1 pixel, but as fonts get smaller this
starts to become increasingly larger compared to the width of the small
font. Zoomed in fonts (or larger than 16 on my display) typically look
better.
- Based on this work I think it would be fairly trivial to add drop
shadows, mirroring and other text effects.

Zoomed in;

closes #2861
/claim #2861
2024-12-27 12:07:37 +04:00
lp . setRenderHint ( QPainter : : Antialiasing ) ;
QFont font ( fontName . has_value ( ) ? fontName . value ( ) : QString ( ) , fontSize ) ;
2026-01-19 07:31:50 +01:00
label . font = font ;
2012-12-28 16:09:59 +01:00
lp . setFont ( font ) ;
Add: give map label text the ability to have an outline (#7598)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Add an outline colour chooser to map label creation window in mapper.
Update createMapLabel Lua function to reflect this as well. Adds three
optional arguments to the end of createMapLabel( ..., outlineRed,
outlineGreen, outlineBlue), default to the same colour as foreground if
not specified.
Also, chosen colours weren't being saved from one dialog to the next
forcing unnecessary typing to replicate a colour scheme when creating
multiple labels, so fix this and allow chosen colours to also save
across Mudlet restarts as well.
#### Motivation for adding to Mudlet
Better user experience, more map design options, prettier maps.
#### Other info (issues closed, discussion etc)
- The outline width is only 1 pixel, but as fonts get smaller this
starts to become increasingly larger compared to the width of the small
font. Zoomed in fonts (or larger than 16 on my display) typically look
better.
- Based on this work I think it would be fairly trivial to add drop
shadows, mirroring and other text effects.

Zoomed in;

closes #2861
/claim #2861
2024-12-27 12:07:37 +04:00
QPen outlinePen ( label . outlineColor ) ;
outlinePen . setWidth ( 1 ) ;
lp . setPen ( outlinePen ) ;
2012-12-28 16:09:59 +01:00
QRectF br ;
Add: give map label text the ability to have an outline (#7598)
<!-- Keep the title short & concise so anyone non-technical can
understand it,
the title appears in PTB changelogs -->
#### Brief overview of PR changes/additions
Add an outline colour chooser to map label creation window in mapper.
Update createMapLabel Lua function to reflect this as well. Adds three
optional arguments to the end of createMapLabel( ..., outlineRed,
outlineGreen, outlineBlue), default to the same colour as foreground if
not specified.
Also, chosen colours weren't being saved from one dialog to the next
forcing unnecessary typing to replicate a colour scheme when creating
multiple labels, so fix this and allow chosen colours to also save
across Mudlet restarts as well.
#### Motivation for adding to Mudlet
Better user experience, more map design options, prettier maps.
#### Other info (issues closed, discussion etc)
- The outline width is only 1 pixel, but as fonts get smaller this
starts to become increasingly larger compared to the width of the small
font. Zoomed in fonts (or larger than 16 on my display) typically look
better.
- Based on this work I think it would be fairly trivial to add drop
shadows, mirroring and other text effects.

Zoomed in;

closes #2861
/claim #2861
2024-12-27 12:07:37 +04:00
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 ) ;
2012-12-28 16:09:59 +01:00
label . size = br . normalized ( ) . size ( ) ;
2025-12-29 22:05:42 +01:00
const QRect brRect = br . normalized ( ) . toRect ( ) ;
label . pix = pix . copy ( brRect . topLeft ( ) . x ( ) , brRect . topLeft ( ) . y ( ) , brRect . width ( ) , brRect . height ( ) ) ;
2024-03-11 15:40:56 +00:00
const QSizeF s = QSizeF ( label . size . width ( ) / zoom , label . size . height ( ) / zoom ) ;
2012-12-28 16:09:59 +01:00
label . size = s ;
2013-03-03 12:22:58 -05:00
label . clickSize = s ;
2017-04-17 21:35:44 -07:00
2023-05-14 15:06:15 +02:00
const int labelId = pA - > createLabelId ( ) ;
2021-01-17 09:02:23 +00:00
if ( Q_LIKELY ( labelId > = 0 ) ) {
pA - > mMapLabels . insert ( labelId , label ) ;
if ( mpMapper ) {
mpMapper - > mp2dMap - > update ( ) ;
2012-12-28 18:05:12 +01:00
}
2011-06-26 23:26:24 +02:00
}
2022-11-11 05:01:28 +00:00
if ( ! temporary ) {
setUnsaved ( __func__ ) ;
}
2021-01-17 09:02:23 +00:00
return labelId ;
2011-06-26 15:23:37 +02:00
}
2022-11-11 05:01:28 +00:00
int TMap : : createMapImageLabel ( int area , QString imagePath , float x , float y , float z , float width , float height , float zoom , bool showOnTop , bool temporary )
2012-12-28 18:05:12 +01:00
{
2021-01-17 09:02:23 +00:00
auto pA = mpRoomDB - > getArea ( area ) ;
if ( ! pA ) {
2017-06-26 16:46:54 +02:00
return - 1 ;
}
2012-12-28 18:05:12 +01:00
TMapLabel label ;
label . size = QSizeF ( width , height ) ;
2017-06-26 16:46:54 +02:00
label . pos = QVector3D ( x , y , z ) ;
2012-12-28 18:05:12 +01:00
label . showOnTop = showOnTop ;
2021-01-17 09:02:23 +00:00
// This method is only called from the TLuaInterpreter class and the value
// passed was hard-coded to this value:
label . noScaling = false ;
2022-11-11 05:01:28 +00:00
label . temporary = temporary ;
2012-12-28 18:05:12 +01:00
2024-03-11 15:40:56 +00:00
const QRectF drawRect = QRectF ( 0 , 0 , static_cast < qreal > ( width * zoom ) , static_cast < qreal > ( height * zoom ) ) ;
const QPixmap imagePixmap = QPixmap ( imagePath ) ;
2017-06-26 16:46:54 +02:00
QPixmap pix = QPixmap ( drawRect . size ( ) . toSize ( ) ) ;
2017-04-29 10:42:28 +02:00
pix . fill ( Qt : : transparent ) ;
2017-06-26 16:46:54 +02:00
QPainter lp ( & pix ) ;
lp . drawPixmap ( QPoint ( 0 , 0 ) , imagePixmap . scaled ( drawRect . size ( ) . toSize ( ) ) ) ;
2012-12-28 18:05:12 +01:00
label . size = QSizeF ( width , height ) ;
label . pix = pix ;
2017-04-16 22:33:35 -07:00
2023-05-14 15:06:15 +02:00
const int labelId = pA - > createLabelId ( ) ;
2021-01-17 09:02:23 +00:00
if ( Q_LIKELY ( labelId > = 0 ) ) {
pA - > mMapLabels . insert ( labelId , label ) ;
if ( mpMapper ) {
mpMapper - > mp2dMap - > update ( ) ;
2012-12-28 18:05:12 +01:00
}
}
2022-11-11 05:01:28 +00:00
if ( ! temporary ) {
setUnsaved ( __func__ ) ;
}
2021-01-17 09:02:23 +00:00
return labelId ;
2012-12-28 18:05:12 +01:00
}
2021-01-17 09:02:23 +00:00
void TMap : : deleteMapLabel ( int area , int labelId )
2011-06-26 15:23:37 +02:00
{
2021-01-17 09:02:23 +00:00
auto pA = mpRoomDB - > getArea ( area ) ;
if ( ! pA ) {
2017-06-26 16:46:54 +02:00
return ;
}
2021-01-17 09:02:23 +00:00
2022-11-11 05:01:28 +00:00
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__ ) ;
}
2022-04-18 10:38:42 +02:00
if ( mpMapper ) {
mpMapper - > mp2dMap - > update ( ) ;
}
2017-06-26 16:46:54 +02:00
}
2011-06-26 15:23:37 +02:00
}
2016-03-14 12:24:01 +00:00
2017-06-26 16:46:54 +02:00
void TMap : : postMessage ( const QString text )
2016-03-14 12:24:01 +00:00
{
2017-06-26 16:46:54 +02:00
mStoredMessages . append ( text ) ;
Host * pHost = mpHost ;
if ( pHost ) {
while ( ! mStoredMessages . isEmpty ( ) ) {
pHost - > postMessage ( mStoredMessages . takeFirst ( ) ) ;
2016-03-14 12:24:01 +00:00
}
}
}
2016-04-28 23:48:08 +01:00
// Used by the 2D mapper to send view center coordinates to 3D one
2017-06-26 16:46:54 +02:00
void TMap : : set3DViewCenter ( const int areaId , const int xPos , const int yPos , const int zPos )
2016-04-28 23:48:08 +01:00
{
2019-08-15 11:56:11 +02:00
# if defined(INCLUDE_3DMAPPER)
2020-03-14 18:26:10 +01:00
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 ) ;
}
2020-03-14 18:26:10 +01:00
}
2022-06-11 01:03:54 +01:00
# else
Q_UNUSED ( areaId )
Q_UNUSED ( xPos )
Q_UNUSED ( yPos )
Q_UNUSED ( zPos )
2019-08-15 11:56:11 +02:00
# endif
2016-04-28 23:48:08 +01:00
}
2016-05-03 04:58:31 +01:00
2017-06-26 16:46:54 +02:00
void TMap : : appendRoomErrorMsg ( const int roomId , const QString msg , const bool isToSetFileViewingRecommended )
2016-05-03 04:58:31 +01:00
{
2017-06-26 16:46:54 +02:00
mMapAuditRoomErrors [ roomId ] . append ( msg ) ;
2016-05-03 04:58:31 +01:00
mIsFileViewingRecommended = isToSetFileViewingRecommended ? true : mIsFileViewingRecommended ;
}
2017-06-26 16:46:54 +02:00
void TMap : : appendAreaErrorMsg ( const int areaId , const QString msg , const bool isToSetFileViewingRecommended )
2016-05-03 04:58:31 +01:00
{
2017-06-26 16:46:54 +02:00
mMapAuditAreaErrors [ areaId ] . append ( msg ) ;
2016-05-03 04:58:31 +01:00
mIsFileViewingRecommended = isToSetFileViewingRecommended ? true : mIsFileViewingRecommended ;
}
2017-06-26 16:46:54 +02:00
void TMap : : appendErrorMsg ( const QString msg , const bool isToSetFileViewingRecommended )
2016-05-03 04:58:31 +01:00
{
2017-06-26 16:46:54 +02:00
mMapAuditErrors . append ( msg ) ;
2016-05-03 04:58:31 +01:00
mIsFileViewingRecommended = isToSetFileViewingRecommended ? true : mIsFileViewingRecommended ;
}
2017-06-26 16:46:54 +02:00
void TMap : : appendErrorMsgWithNoLf ( const QString msg , const bool isToSetFileViewingRecommended )
2016-05-03 04:58:31 +01:00
{
QString text = msg ;
2017-06-26 16:46:54 +02:00
text . replace ( QChar : : LineFeed , QChar : : Space ) ;
mMapAuditErrors . append ( text ) ;
2016-05-03 04:58:31 +01:00
mIsFileViewingRecommended = isToSetFileViewingRecommended ? true : mIsFileViewingRecommended ;
}
2017-06-26 16:46:54 +02:00
const QString TMap : : createFileHeaderLine ( const QString title , const QChar fillChar )
2016-05-03 04:58:31 +01:00
{
QString text ;
2017-06-26 16:46:54 +02:00
if ( title . length ( ) < = 76 ) {
2021-12-07 06:21:39 +01:00
text = qsl ( " %1 %2 %1 \n " ) . arg ( QString ( fillChar ) . repeated ( ( 78 - title . length ( ) ) / 2 ) , title ) ;
2017-06-26 16:46:54 +02:00
} else {
2016-05-03 04:58:31 +01:00
text = title ;
2017-06-26 16:46:54 +02:00
text . append ( QChar : : LineFeed ) ;
2016-05-03 04:58:31 +01:00
}
return text ;
}
2017-06-26 16:46:54 +02:00
void TMap : : pushErrorMessagesToFile ( const QString title , const bool isACleanup )
2016-05-03 04:58:31 +01:00
{
2017-06-26 16:46:54 +02:00
Host * pHost = mpHost ;
if ( ! pHost ) {
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:
2017-06-26 16:46:54 +02:00
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
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."
2017-06-26 16:46:54 +02:00
mapAuditErrors . swap ( mMapAuditErrors ) ;
mapAuditAreaErrors . swap ( mMapAuditAreaErrors ) ;
mapAuditRoomErrors . swap ( mMapAuditRoomErrors ) ;
2016-05-03 04:58:31 +01:00
2017-06-26 16:46:54 +02:00
if ( mapAuditErrors . isEmpty ( ) & & mapAuditAreaErrors . isEmpty ( ) & & mapAuditRoomErrors . isEmpty ( ) & & isACleanup ) {
2016-05-03 04:58:31 +01:00
mIsFileViewingRecommended = false ;
return ; // Nothing to do
}
2017-06-26 16:46:54 +02:00
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 ' ) ;
;
2016-05-03 04:58:31 +01:00
}
2017-06-26 16:46:54 +02:00
pHost - > mErrorLogStream < < createFileHeaderLine ( tr ( " Area issues " ) , QLatin1Char ( ' = ' ) ) ;
QMapIterator < int , QList < QString > > itAreasMsg ( mapAuditAreaErrors ) ;
while ( itAreasMsg . hasNext ( ) ) {
2016-05-03 04:58:31 +01:00
itAreasMsg . next ( ) ;
QString titleText ;
2017-06-26 16:46:54 +02:00
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 ( ) ) ;
2016-05-03 04:58:31 +01:00
}
2017-06-26 16:46:54 +02:00
pHost - > mErrorLogStream < < createFileHeaderLine ( titleText , QLatin1Char ( ' - ' ) ) ;
QListIterator < QString > itMapAreaMsg ( itAreasMsg . value ( ) ) ;
while ( itMapAreaMsg . hasNext ( ) ) {
pHost - > mErrorLogStream < < itMapAreaMsg . next ( ) < < QLatin1Char ( ' \n ' ) ;
2016-05-03 04:58:31 +01:00
}
}
2017-06-26 16:46:54 +02:00
pHost - > mErrorLogStream < < createFileHeaderLine ( tr ( " Room issues " ) , QLatin1Char ( ' = ' ) ) ;
QMapIterator < int , QList < QString > > itRoomsMsg ( mapAuditRoomErrors ) ;
while ( itRoomsMsg . hasNext ( ) ) {
2016-05-03 04:58:31 +01:00
itRoomsMsg . next ( ) ;
QString titleText ;
2017-06-26 16:46:54 +02:00
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 ( ) ) ;
2016-05-03 04:58:31 +01:00
}
2017-06-26 16:46:54 +02:00
pHost - > mErrorLogStream < < createFileHeaderLine ( titleText , QLatin1Char ( ' - ' ) ) ;
QListIterator < QString > itMapRoomMsg ( itRoomsMsg . value ( ) ) ;
while ( itMapRoomMsg . hasNext ( ) ) {
pHost - > mErrorLogStream < < itMapRoomMsg . next ( ) < < QLatin1Char ( ' \n ' ) ;
;
2016-05-03 04:58:31 +01:00
}
}
2017-06-26 16:46:54 +02:00
pHost - > mErrorLogStream < < createFileHeaderLine ( tr ( " End of report " ) , QLatin1Char ( ' # ' ) ) ;
2016-05-03 04:58:31 +01:00
pHost - > mErrorLogStream . flush ( ) ;
mapAuditErrors . clear ( ) ;
mapAuditAreaErrors . clear ( ) ;
mapAuditRoomErrors . clear ( ) ;
2017-06-26 16:46:54 +02:00
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 \" . " )
2025-01-08 10:04:50 +01:00
. arg ( mudlet : : getMudletPath ( enums : : profileLogErrorsFilePath , mProfileName ) , title ) ) ;
2017-06-26 16:46:54 +02:00
} 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 \" . " )
2025-01-08 10:04:50 +01:00
. arg ( mudlet : : getMudletPath ( enums : : profileLogErrorsFilePath , mProfileName ) , title ) ) ;
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
2018-09-02 07:43:09 +02: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 ) ;
2017-06-26 16:46:54 +02:00
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
2020-10-26 15:14:15 +01:00
if ( mImportRunning ) {
2023-05-14 15:06:15 +02:00
const QString warnMsg = tr ( " [ WARN ] - Attempt made to download an XML map when one has already been \n "
2017-06-26 16:46:54 +02:00
" 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 ;
}
2020-10-26 15:14:15 +01:00
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 ;
2018-09-02 07:43:09 +02:00
if ( remoteUrl . isEmpty ( ) ) {
2018-10-04 08:09:57 +02:00
if ( ! getMmpMapLocation ( ) . isEmpty ( ) ) {
url = QUrl : : fromUserInput ( getMmpMapLocation ( ) ) ;
} else {
2021-12-07 06:21:39 +01:00
url = QUrl : : fromUserInput ( qsl ( " https://www.%1/maps/map.xml " ) . arg ( pHost - > mUrl ) ) ;
2018-10-04 08:09:57 +02:00
}
2017-06-26 16:46:54 +02:00
} else {
2018-09-02 07:43:09 +02:00
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
}
2017-06-26 16:46:54 +02:00
if ( ! url . isValid ( ) ) {
2023-05-14 15:06:15 +02:00
const QString errMsg = tr ( " [ WARN ] - Attempt made to download an XML from an invalid URL. The URL was: \n "
2017-06-26 16:46:54 +02:00
" %1 \n "
" and the error message (may contain technical details) was: "
" \" %2 \" . " )
. arg ( url . toString ( ) , url . errorString ( ) ) ;
postMessage ( errMsg ) ;
2020-10-26 15:14:15 +01:00
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 ;
}
2020-01-24 11:11:54 -08:00
// Check to ensure we have a map directory to save the map files to.
2023-05-14 15:06:15 +02:00
const QDir toProfileDir ;
2025-01-08 10:04:50 +01:00
const QString toProfileDirPathString = mudlet : : getMudletPath ( enums : : profileMapsPath , mProfileName ) ;
2020-01-24 11:11:54 -08:00
if ( ! toProfileDir . mkpath ( toProfileDirPathString ) ) {
2023-05-14 15:06:15 +02:00
const QString errMsg = tr ( " [ ERROR ] - Unable to use or create directory to store map. \n "
2020-01-24 11:11:54 -08:00
" 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 ) ;
2020-10-26 15:14:15 +01:00
mImportRunning = false ;
2020-01-24 11:11:54 -08:00
return ;
}
2018-09-02 07:43:09 +02:00
if ( localFileName . isEmpty ( ) ) {
2019-09-30 10:22:07 +02:00
if ( url . toString ( ) . endsWith ( QLatin1String ( " xml " ) ) ) {
2025-01-08 10:04:50 +01:00
mLocalMapFileName = mudlet : : getMudletPath ( enums : : profileXmlMapPathFileName , mProfileName ) ;
2019-09-30 10:22:07 +02:00
} else {
2025-01-08 10:04:50 +01:00
mLocalMapFileName = mudlet : : getMudletPath ( enums : : profileMapPathFileName , mProfileName , qsl ( " map.dat " ) ) ;
2019-09-30 10:22:07 +02:00
}
2017-06-26 16:46:54 +02:00
} else {
2018-09-02 07:43:09 +02:00
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
}
2017-06-26 16:46:54 +02:00
QNetworkRequest request = QNetworkRequest ( url ) ;
2019-09-23 06:03:35 +02:00
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 ;
2017-06-26 16:46:54 +02:00
2023-05-14 15:06:15 +02:00
const QString infoMsg = tr ( " [ INFO ] - Map download initiated, please wait... " ) ;
2017-06-26 16:46:54 +02:00
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!
2019-09-23 06:03:35 +02:00
mpNetworkReply = mpNetworkAccessManager - > get ( request ) ;
2023-05-29 22:03:34 +03:00
//: %1 is the name of the current Mudlet profile
2026-04-25 13:02:24 +02:00
const QString label = tr ( " Downloading map file for use in %1... " ) . arg ( mProfileName ) ;
2023-05-29 22:03:34 +03:00
//: This is a title of a progress window.
2026-04-25 13:02:24 +02:00
createTransferProgress ( tr ( " Map download " ) , label , true ) ;
2017-06-26 16:46:54 +02:00
2018-07-26 13:30:02 +02:00
connect ( mpNetworkReply , & QNetworkReply : : downloadProgress , this , & TMap : : slot_setDownloadProgress ) ;
2020-11-18 20:07:10 +00:00
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
2017-06-26 16:46:54 +02:00
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
{
2020-10-26 15:14:15 +01:00
if ( mImportRunning ) {
2017-06-26 16:46:54 +02:00
if ( errMsg ) {
* errMsg = tr ( " loadMap: unable to perform request, a map is already being downloaded or \n "
" imported at user request. " ) ;
} else {
2023-05-14 15:06:15 +02:00
const QString warnMsg = qsl ( " [ WARN ] - Attempt made to import an XML map when one is already being \n "
2017-06-26 16:46:54 +02:00
" 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 ;
}
2020-10-26 15:14:15 +01:00
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
2023-05-14 15:06:15 +02:00
const bool result = readXmlMapFile ( file , errMsg ) ;
2020-10-26 15:14:15 +01:00
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 ;
}
2017-06-26 16:46:54 +02:00
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 ) ;
2017-06-26 16:46:54 +02:00
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 ;
2017-06-26 16:46:54 +02:00
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 ;
}
2026-04-25 13:02:24 +02: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
isLocalImport = true ;
2023-05-29 22:03:34 +03:00
//: This is a title of a progress window.
2026-04-25 13:02:24 +02:00
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 ( ) ;
2017-06-26 16:46:54 +02:00
XMLimport reader ( pHost ) ;
2023-04-27 19:50:32 +02:00
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
2023-04-14 21:24:05 +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 ( ) ;
2023-04-27 19:50:32 +02:00
if ( success ) {
2023-04-14 21:24:05 +01:00
mpMapper - > resetAreaComboBoxToPlayerRoomArea ( ) ;
2023-04-27 19:50:32 +02:00
} 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
}
}
2023-04-27 19:50:32 +02:00
if ( ! success & & errMsg ) {
2023-04-14 21:24:05 +01:00
* errMsg = tr ( " loadMap: failure to import XML map file, further information may be available \n "
" in main console! " ) ;
}
2017-06-26 16:46:54 +02:00
if ( isLocalImport ) {
2026-04-25 13:02:24 +02:00
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
}
2023-04-14 21:24:05 +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
2023-04-27 19:50:32 +02: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
}
2022-11-24 08:42:28 +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
{
2026-04-25 13:02:24 +02: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 ;
}
2026-04-25 13:02:24 +02:00
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;
2026-04-25 13:02:24 +02:00
updateTransferProgressRange ( 0 , mExpectedFileSize ) ;
} else if ( total ! = - 1 & & transferProgressMaximum ( ) ! = static_cast < int > ( total ) ) {
2022-11-24 08:42:28 +01:00
// 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
2026-04-25 13:02:24 +02:00
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
}
2026-04-25 13:02:24 +02: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 ( )
{
2023-05-14 15:06:15 +02:00
const QString alertMsg = tr ( " [ ALERT ] - Map download was canceled, on user's request. " ) ;
2017-06-26 16:46:54 +02:00
postMessage ( alertMsg ) ;
2026-04-25 13:02:24 +02:00
clearTransferProgress ( ) ;
2017-06-26 16:46:54 +02: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
mpNetworkReply - > abort ( ) ; // Will indirectly cause error() AND replyFinished signals to be sent
}
}
2017-06-26 16:46:54 +02:00
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
{
2017-06-26 16:46:54 +02: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 ;
}
2017-06-26 16:46:54 +02:00
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
2023-05-29 22:33:24 +03:00
const QString errMsg = tr ( " [ ERROR ] - Map download encountered an error: \n %1 " ) . arg ( mpNetworkReply - > errorString ( ) ) ;
2017-06-26 16:46:54 +02:00
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
}
}
2017-06-26 16:46:54 +02: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
{
2019-09-30 10:22:07 +02:00
auto cleanup = [ this , reply ] ( ) {
reply - > deleteLater ( ) ;
2021-09-18 11:21:29 -05:00
mpNetworkReply = nullptr ;
2019-09-30 10:22:07 +02:00
2026-04-25 13:02:24 +02:00
// We don't dismiss the progress display until here as we now use it to
// inform about post-download operations
clearTransferProgress ( ) ;
2019-09-30 10:22:07 +02:00
mLocalMapFileName . clear ( ) ;
mExpectedFileSize = 0 ;
2020-10-26 15:14:15 +01:00
// We have finished with the XMLimporter so must clear the flag
mImportRunning = false ;
2019-09-30 10:22:07 +02:00
} ;
2017-06-26 16:46:54 +02:00
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. " ;
}
2023-05-29 22:33:24 +03:00
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()
2022-11-24 08:42:28 +01:00
}
2023-04-25 19:28:34 +02:00
// Separate the two kinds of files to gain QSaveFile's atomic write behavior
QSaveFile writeFile ( mLocalMapFileName ) ;
QFile readFile ( mLocalMapFileName ) ;
if ( ! writeFile . open ( QFile : : WriteOnly ) ) {
2023-05-14 15:06:15 +02:00
const QString alertMsg = tr ( " [ ALERT ] - Map download failed, unable to open destination file: \n %1. " ) . arg ( mLocalMapFileName ) ;
2022-11-24 08:42:28 +01:00
postMessage ( alertMsg ) ;
cleanup ( ) ;
return ;
}
// The QNetworkReply is Ok here:
2023-04-25 19:28:34 +02:00
if ( writeFile . write ( reply - > readAll ( ) ) = = - 1 ) {
2023-05-14 15:06:15 +02:00
const QString alertMsg = tr ( " [ ALERT ] - Map download failed, unable to write destination file: \n %1. " ) . arg ( mLocalMapFileName ) ;
2022-11-24 08:42:28 +01:00
postMessage ( alertMsg ) ;
cleanup ( ) ;
return ;
}
2023-04-25 19:28:34 +02:00
if ( ! writeFile . commit ( ) ) {
2026-03-23 07:01:30 +01:00
const QString alertMsg = tr ( " [ ALERT ] - Map download failed, unable to save destination file: \n %1 \n reason: %2 " ) . arg ( mLocalMapFileName , writeFile . errorString ( ) ) ;
postMessage ( alertMsg ) ;
cleanup ( ) ;
return ;
2023-04-25 19:28:34 +02: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
2022-11-24 08:42:28 +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
2023-05-14 15:06:15 +02:00
const QString infoMsg = tr ( " [ INFO ] - ... map downloaded and stored, now parsing it... " ) ;
2022-11-24 08:42:28 +01:00
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
2022-11-24 08:42:28 +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:
2026-04-25 13:02:24 +02:00
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
2022-11-24 08:42:28 +01:00
bool parsingWasSuccessful ;
QString parsingFileName ;
2023-04-25 19:28:34 +02:00
if ( ! readFile . fileName ( ) . endsWith ( qsl ( " xml " ) , Qt : : CaseInsensitive ) ) {
parsingFileName = readFile . fileName ( ) ;
2022-11-24 08:42:28 +01:00
parsingWasSuccessful = pHost - > mpConsole - > loadMap ( parsingFileName ) ;
} else {
parsingFileName = mLocalMapFileName ;
2023-04-25 19:28:34 +02:00
if ( ! readFile . open ( QFile : : OpenMode ( QFile : : ReadOnly | QFile : : Text ) ) ) {
2023-05-14 15:06:15 +02:00
const QString alertMsg = tr ( " [ ERROR ] - Map download problem, unable to read destination file: \n %1. " ) . arg ( parsingFileName ) ;
2022-11-24 08:42:28 +01:00
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
}
2022-11-24 08:42:28 +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.
2023-04-25 19:28:34 +02:00
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
}
2022-11-24 08:42:28 +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...
2023-05-14 15:06:15 +02:00
const QString alertMsg = tr ( " [ ERROR ] - Map download problem, failure in parsing destination file: \n %1. " ) . arg ( parsingFileName ) ;
2022-11-24 08:42:28 +01:00
postMessage ( alertMsg ) ;
}
2026-04-25 13:02:24 +02:00
if ( mpMapper ) {
mpMapper - > updateEmptyStateOverlay ( ) ;
}
2019-09-30 10:22:07 +02:00
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
}
2017-06-26 16:46:54 +02: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
{
2026-04-25 13:02:24 +02: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 ( ) ;
}
}
2017-06-26 16:46:54 +02:00
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
{
2026-04-25 13:02:24 +02: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
}
2026-04-25 13:02:24 +02: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 ( ) ) ;
2026-04-25 13:02:24 +02:00
}
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 ) ;
2026-04-25 13:02:24 +02:00
} 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 ) ;
2026-04-25 13:02:24 +02:00
} 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 ) ;
2026-04-25 13:02:24 +02:00
} 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 ;
2026-04-25 13:02:24 +02:00
}
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 ( ) ) ;
2026-04-25 13:02:24 +02:00
}
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 ( ) ;
2026-04-25 13:02:24 +02:00
} 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 ( ) ;
2026-04-25 13:02:24 +02:00
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 ;
}
2018-10-04 08:09:57 +02:00
void TMap : : setMmpMapLocation ( const QString & location )
{
2026-04-25 13:02:24 +02:00
if ( mMmpMapLocation = = location ) {
return ;
}
2018-10-04 08:09:57 +02:00
mMmpMapLocation = location ;
qDebug ( ) < < " MMP map registered at " < < mMmpMapLocation ;
2026-04-25 13:02:24 +02:00
emit signal_mmpMapLocationChanged ( ) ;
2018-10-04 08:09:57 +02:00
}
QString TMap : : getMmpMapLocation ( ) const
{
return mMmpMapLocation ;
}
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 } ;
2021-04-05 15:49:30 +02:00
if ( destination . isEmpty ( ) ) {
2025-01-08 10:04:50 +01:00
const QString destFolder = mudlet : : getMudletPath ( enums : : profileMapsPath , mProfileName ) ;
2023-05-14 15:06:15 +02:00
const QDir destDir ( destFolder ) ;
2022-02-08 11:34:20 +00:00
if ( ! destDir . exists ( ) ) {
destDir . mkdir ( destFolder ) ;
}
2025-01-08 10:04:50 +01:00
destination = mudlet : : getMudletPath ( enums : : profileDateTimeStampedJsonMapPathFileName , mProfileName , QDateTime : : currentDateTime ( ) . toString ( qsl ( " yyyy-MM-dd#HH-mm-ss " ) ) ) ;
2021-04-05 15:49:30 +02:00
}
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 ) {
2021-12-07 06:21:39 +01:00
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 ) {
2022-11-11 05:01:28 +00:00
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 ) ;
2023-05-29 22:03:34 +03:00
//: 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 ( ) ;
2023-04-25 19:28:34 +02:00
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 ;
2023-05-30 13:25:07 -04:00
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 ) {
2023-04-25 19:28:34 +02:00
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 ;
2021-12-07 06:21:39 +01:00
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:
2024-03-11 15:40:56 +00:00
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 ) ;
2024-03-11 15:40:56 +00:00
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 ) ;
2024-03-11 15:40:56 +00:00
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 ) ) ;
2023-04-25 19:28:34 +02:00
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
2021-12-07 06:21:39 +01: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 ) {
2021-12-07 06:21:39 +01:00
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 < < " \" . " ;
2021-12-07 06:21:39 +01:00
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
}
2024-03-11 15:40:56 +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 ;
2024-03-11 15:40:56 +00:00
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. " ;
2021-12-07 06:21:39 +01:00
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):
2021-04-19 08:07:25 +02:00
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 ,
2021-04-19 08:07:25 +02:00
( translatableTexts ? tr ( " invalid format version \" %1 \" detected " ) . arg ( formatVersion , 0 , ' f ' , 3 , QLatin1Char ( ' 0 ' ) )
2021-12-07 06:21:39 +01:00
: 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 {
2021-04-19 08:07:25 +02:00
qDebug ( ) . nospace ( ) . noquote ( ) < < " TMap::readJsonMapFile( \" " < < source < < " \" ) INFO - Version information was not found. This is not likely to be a Mudlet JSON map file. " ;
2021-12-07 06:21:39 +01:00
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 ) ;
2023-05-29 22:03:34 +03:00
//: 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 ( ) ;
2022-08-01 09:29:09 +02:00
if ( mapObj . contains ( QLatin1String ( " userData " ) ) ) {
readJsonUserData ( mapObj [ QLatin1String ( " userData " ) ] . toObject ( ) ) ;
}
2023-05-14 15:06:15 +02:00
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 ( ) ) {
2024-03-11 15:40:56 +00:00
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 ;
2023-05-14 15:06:15 +02:00
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 ( ) ) {
2023-05-14 15:06:15 +02:00
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:
2021-04-11 09:53:43 +02:00
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 ) ;
2021-07-20 12:50:19 +01:00
// 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 ( ) ) ) ;
2024-03-11 15:40:56 +00:00
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 {
2024-03-11 15:40:56 +00:00
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 ( ) ;
}
2023-05-14 15:06:15 +02:00
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
}
2026-01-18 11:41:17 +01:00
void TMap : : updateArea ( int areaId )
2020-10-23 14:49:42 +02:00
{
2024-04-22 18:04:08 +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 ( 0 ms , this , [ this , areaId ] ( ) {
2024-04-22 18:04:08 +02:00
debounce = false ;
2020-10-23 14:49:42 +02:00
# if defined(INCLUDE_3DMAPPER)
2024-04-22 18:04:08 +02:00
if ( mpM ) {
mpM - > update ( ) ;
}
2020-10-23 14:49:42 +02:00
# endif
2024-04-22 18:04:08 +02:00
if ( mpMapper ) {
if ( mpMapper - > mp2dMap ) {
mpMapper - > mp2dMap - > mNewMoveAction = true ;
mpMapper - > mp2dMap - > update ( ) ;
}
}
2026-01-18 11:41:17 +01:00
emit signal_areaChanged ( areaId ) ;
2024-04-22 18:04:08 +02:00
} ) ;
2020-10-23 14:49:42 +02:00
}
}
2021-01-05 16:14:41 +01: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 ) ;
2021-01-05 16:14:41 +01:00
} 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 ) ) {
2021-01-05 16:14:41 +01:00
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 ) ) {
2021-01-05 16:14:41 +01:00
if ( 16 < env & & env < 232 ) {
2023-05-14 15:06:15 +02:00
quint8 const base = env - 16 ;
2021-01-05 16:14:41 +01:00
quint8 r = base / 36 ;
quint8 g = ( base - ( r * 36 ) ) / 6 ;
quint8 b = ( base - ( r * 36 ) ) - ( g * 6 ) ;
2021-08-08 16:42:38 +09:00
r = r = = 0 ? 0 : ( r - 1 ) * 40 + 95 ;
g = g = = 0 ? 0 : ( g - 1 ) * 40 + 95 ;
b = b = = 0 ? 0 : ( b - 1 ) * 40 + 95 ;
2021-01-05 16:14:41 +01:00
color = QColor ( r , g , b , 255 ) ;
} else if ( 231 < env & & env < 256 ) {
2023-05-14 15:06:15 +02:00
quint8 const k = ( ( env - 232 ) * 10 ) + 8 ;
2021-01-05 16:14:41 +01:00
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 ) ;
2021-01-05 16:14:41 +01:00
}
return color ;
}
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 ;
}
2022-11-11 05:01:28 +00:00
void TMap : : setUnsaved ( const char * fromWhere )
{
# if !defined(DEBUG_MAPAUTOSAVE)
2025-04-27 18:48:34 +01:00
Q_UNUSED ( fromWhere )
2022-11-11 05:01:28 +00:00
# else
QString nowString = QDateTime : : currentDateTimeUtc ( ) . toString ( " HH:mm:ss.zzz " ) ;
qDebug ( ) . nospace ( ) . noquote ( ) < < " TMap::setUnsaved(...) INFO - called at: " < < nowString < < " from: " < < fromWhere < < " . " ;
# endif
mUnsavedMap = true ;
}
2023-04-24 21:09:49 +01:00
2025-12-31 07:30:38 +01:00
void TMap : : setSaveError ( bool state )
{
if ( mSaveError ! = state ) {
mSaveError = state ;
emit signal_saveErrorChanged ( state ) ;
}
}
2023-04-24 21:09:49 +01:00
void TMap : : setDefaultAreaShown ( bool state )
{
if ( mShowDefaultArea ! = state ) {
mShowDefaultArea = state ;
if ( ! mpMapper . isNull ( ) ) {
mpMapper - > updateAreaComboBox ( ) ;
}
}
}