Added a new command and fixed a crash bug

Created a new client command called 'ls_cmds' that will
list all available commands. This more like a revival of
an old command that existed in the past. It's function
was once added to 'about' but now it has been re-spun
into it's own command once again.

Fixed a bug that caused the 'connect' command to crash
the client after calling it with the '-save' option and
then the 'ls_cmds' command. The connect command actual
creates a SaveBookmark command object when called with
the '-save' option. The problem was its constructor was
replacing it's existing object pointer in the command
list with a pointer that was about to get destroyed
after calling the '-save' option, causing the command
object list to contain a null pointer for save_bookmark.
This commit is contained in:
Maurice ONeal 2020-03-30 12:23:21 -04:00
parent 3f39ba8767
commit 347e01eeff
7 changed files with 107 additions and 53 deletions

View File

@ -20,8 +20,11 @@ SaveBookmark::SaveBookmark(QObject *parent) : Command(parent)
{ {
setObjectName("save_bookmark"); setObjectName("save_bookmark");
if (!Shared::clientCmds->contains(objectName()))
{
Shared::clientCmds->insert(objectName(), this); Shared::clientCmds->insert(objectName(), this);
} }
}
QString SaveBookmark::shortText() {return tr("create or update a host bookmark.");} QString SaveBookmark::shortText() {return tr("create or update a host bookmark.");}
QString SaveBookmark::ioText() {return tr("[-name (text) {-addr (text)} {-port (text)} {-force}]/[text]");} QString SaveBookmark::ioText() {return tr("[-name (text) {-addr (text)} {-port (text)} {-force}]/[text]");}
@ -76,8 +79,8 @@ void SaveBookmark::run(const QString &name, QStringList &args)
if (file.open(QFile::WriteOnly | QFile::Truncate)) if (file.open(QFile::WriteOnly | QFile::Truncate))
{ {
QString addr = getParam("-addr", args); auto addr = getParam("-addr", args);
int port = getParam("-port", args).toInt(); auto port = getParam("-port", args).toInt();
if (addr.isEmpty()) addr = *Shared::hostAddress; if (addr.isEmpty()) addr = *Shared::hostAddress;
if (port == 0) port = *Shared::hostPort; if (port == 0) port = *Shared::hostPort;
@ -124,9 +127,9 @@ void SaveBookmark::dataIn(const QString &argsLine)
} }
else else
{ {
QStringList args = parseArgs(argsLine); auto args = parseArgs(argsLine);
bool force = argExists("-force", args); auto force = argExists("-force", args);
QString name = getParam("-name", args); auto name = getParam("-name", args);
if (name.isEmpty()) if (name.isEmpty())
{ {
@ -173,8 +176,8 @@ void ListBookmarks::dataIn(const QString &argsLine)
void DeleteBookmark::dataIn(const QString &argsLine) void DeleteBookmark::dataIn(const QString &argsLine)
{ {
QStringList args = parseArgs(argsLine); auto args = parseArgs(argsLine);
QString name = getParam("-name", args); auto name = getParam("-name", args);
if (name.isEmpty()) if (name.isEmpty())
{ {
@ -182,7 +185,7 @@ void DeleteBookmark::dataIn(const QString &argsLine)
} }
else else
{ {
QString path = appDataDir() + BOOKMARK_FOLDER + "/" + name + ".json"; auto path = appDataDir() + BOOKMARK_FOLDER + "/" + name + ".json";
if (!QFile::remove(path)) if (!QFile::remove(path))
{ {
@ -193,8 +196,8 @@ void DeleteBookmark::dataIn(const QString &argsLine)
void SeeBookmark::dataIn(const QString &argsLine) void SeeBookmark::dataIn(const QString &argsLine)
{ {
QStringList args = parseArgs(argsLine); auto args = parseArgs(argsLine);
QString name = getParam("-name", args); auto name = getParam("-name", args);
if (name.isEmpty()) if (name.isEmpty())
{ {
@ -202,13 +205,13 @@ void SeeBookmark::dataIn(const QString &argsLine)
} }
else else
{ {
QString path = appDataDir() + BOOKMARK_FOLDER + "/" + name + ".json"; auto path = appDataDir() + BOOKMARK_FOLDER + "/" + name + ".json";
QFile file(path, this); QFile file(path, this);
if (file.open(QFile::ReadOnly)) if (file.open(QFile::ReadOnly))
{ {
QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); auto doc = QJsonDocument::fromJson(file.readAll());
cacheTxt(TEXT, "address: " + doc.object().value("address").toString() + "\n"); cacheTxt(TEXT, "address: " + doc.object().value("address").toString() + "\n");
cacheTxt(TEXT, "port: " + QString::number(doc.object().value("port").toInt()) + "\n"); cacheTxt(TEXT, "port: " + QString::number(doc.object().value("port").toInt()) + "\n");

View File

@ -89,13 +89,18 @@ QString Resume::longText() {return TXT_Term;}
void Connect::dataIn(const QString &argsLine) void Connect::dataIn(const QString &argsLine)
{ {
QStringList args = parseArgs(argsLine); auto args = parseArgs(argsLine);
*Shared::hostAddress = getParam("-addr", args); *Shared::hostAddress = getParam("-addr", args);
*Shared::hostPort = getParam("-port", args).toUShort(); *Shared::hostPort = getParam("-port", args).toUShort();
QString saveName = getParam("-save", args); auto saveName = getParam("-save", args);
QString loadName = getParam("-load", args); auto loadName = getParam("-load", args);
if (*Shared::hostPort == 0)
{
*Shared::hostPort = DEFAULT_PORT;
}
if (!saveName.isEmpty()) if (!saveName.isEmpty())
{ {
@ -108,7 +113,7 @@ void Connect::dataIn(const QString &argsLine)
if (file.open(QFile::ReadOnly)) if (file.open(QFile::ReadOnly))
{ {
QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); auto doc = QJsonDocument::fromJson(file.readAll());
*Shared::hostAddress = doc.object().value("address").toString(); *Shared::hostAddress = doc.object().value("address").toString();
*Shared::hostPort = static_cast<quint16>(doc.object().value("port").toInt()); *Shared::hostPort = static_cast<quint16>(doc.object().value("port").toInt());
@ -129,10 +134,6 @@ void Connect::dataIn(const QString &argsLine)
{ {
cacheTxt(ERR, "err: '" + *Shared::hostAddress + "' is not a valid address.\n"); cacheTxt(ERR, "err: '" + *Shared::hostAddress + "' is not a valid address.\n");
} }
else if (*Shared::hostPort == 0)
{
cacheTxt(ERR, "err: The host port cannot be 0.\n");
}
else else
{ {
emit connectToHost(); emit connectToHost();

View File

@ -24,10 +24,21 @@ About::About(QObject *parent) : Command(parent)
} }
void About::onStartup() {dataIn(QString());} void About::onStartup() {dataIn(QString());}
QString About::shortText() {return tr("display information about this MRCI client and display all available commands.");} QString About::shortText() {return tr("display information about the client or a command.");}
QString About::ioText() {return tr("[{cmd_name}]/[text]");} QString About::ioText() {return tr("[{cmd_name}]/[text]");}
QString About::longText() {return TXT_About;} QString About::longText() {return TXT_About;}
ListCmds::ListCmds(QObject *parent) : Command(parent)
{
setObjectName("ls_cmds");
Shared::clientCmds->insert(objectName(), this);
}
QString ListCmds::shortText() {return tr("display all available commands.");}
QString ListCmds::ioText() {return tr("[none]/[text]");}
QString ListCmds::longText() {return TXT_ListCmds;}
void About::dispInfo(Command *cmdObj) void About::dispInfo(Command *cmdObj)
{ {
QString txt; QString txt;
@ -86,25 +97,13 @@ bool About::dispInfo(const QString &cmdName)
} }
} }
void About::listCmds(QHash<QString, Command *> *cmdObjs, QTextStream &txtOut, int largestCmd)
{
QStringList cmdNames = cmdObjs->keys();
cmdNames.sort(Qt::CaseInsensitive);
for (int i = 0; i < cmdNames.size(); ++i)
{
wordWrap(cmdNames[i].leftJustified(largestCmd, ' ') + " - ", txtOut, cmdObjs->value(cmdNames[i])->shortText(), Shared::mainWidget);
}
}
void About::dataIn(const QString &argsLine) void About::dataIn(const QString &argsLine)
{ {
QStringList args = parseArgs(argsLine); auto args = parseArgs(argsLine);
if (args.size() > 0) if (args.size() > 0)
{ {
QString cmdName = args[0].toLower().trimmed(); auto cmdName = args[0].toLower().trimmed();
if (!dispInfo(cmdName)) if (!dispInfo(cmdName))
{ {
@ -120,21 +119,8 @@ void About::dataIn(const QString &argsLine)
txtOut << "Based on QT " << QT_VERSION_STR << " " << 8 * QT_POINTER_SIZE << "bit" << endl << endl; txtOut << "Based on QT " << QT_VERSION_STR << " " << 8 * QT_POINTER_SIZE << "bit" << endl << endl;
txtOut << "The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE" << endl; txtOut << "The program is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE" << endl;
txtOut << "WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE." << endl << endl; txtOut << "WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE." << endl << endl;
txtOut << "usage: <command> <arguments>" << endl << endl; txtOut << "run: 'ls_cmds' to see all available commands." << endl << endl;
txtOut << "<command>" << endl << endl; txtOut << "for more detailed information about a command run: 'about <command>'" << endl << endl;
QStringList cmdNames = Shared::clientCmds->keys() + Shared::hostDocs->keys();
int largestCmd = 0;
for (int i = 0; i < cmdNames.size(); ++i)
{
if (cmdNames[i].size() > largestCmd) largestCmd = cmdNames[i].size();
}
listCmds(Shared::clientCmds, txtOut, largestCmd);
listCmds(Shared::hostDocs, txtOut, largestCmd);
txtOut << endl << endl << "for more detailed information about a command type: about <command>" << endl << endl;
cacheTxt(TEXT, txt); cacheTxt(TEXT, txt);
} }
@ -144,3 +130,40 @@ void About::run()
{ {
dataIn(QString()); dataIn(QString());
} }
void ListCmds::ls(QHash<QString, Command *> *cmdObjs, QTextStream &txtOut, const QString &title)
{
if (!cmdObjs->isEmpty())
{
auto cmdNames = cmdObjs->keys();
auto largestCmd = 0;
for (int i = 0; i < cmdNames.size(); ++i)
{
if (cmdNames[i].size() > largestCmd) largestCmd = cmdNames[i].size();
}
cmdNames.sort(Qt::CaseInsensitive);
txtOut << endl;
txtOut << title << endl << endl;
for (int i = 0; i < cmdNames.size(); ++i)
{
wordWrap(cmdNames[i].leftJustified(largestCmd, ' ') + " - ", txtOut, cmdObjs->value(cmdNames[i])->shortText(), Shared::mainWidget);
}
}
}
void ListCmds::dataIn(const QString &argsLine)
{
Q_UNUSED(argsLine)
QString txt;
QTextStream txtOut(&txt);
ls(Shared::clientCmds, txtOut, "Client Commands:");
ls(Shared::hostDocs, txtOut, "Host Commands:");
cacheTxt(TEXT, txt);
}

View File

@ -28,7 +28,6 @@ class About : public Command
private: private:
void dispInfo(Command *cmdObj); void dispInfo(Command *cmdObj);
void listCmds(QHash<QString, Command *> *cmdObjs, QTextStream &txtOut, int largestCmd);
bool dispInfo(const QString &cmdName); bool dispInfo(const QString &cmdName);
bool dispClientCmd(const QString &cmdName); bool dispClientCmd(const QString &cmdName);
bool dispHostCmd(const QString &cmdName); bool dispHostCmd(const QString &cmdName);
@ -49,4 +48,27 @@ public slots:
void onStartup(); void onStartup();
}; };
//--------------------------
class ListCmds : public Command
{
Q_OBJECT
private:
void ls(QHash<QString, Command *> *cmdObjs, QTextStream &txtOut, const QString &title);
public:
QString shortText();
QString ioText();
QString longText();
explicit ListCmds(QObject *parent = nullptr);
public slots:
void dataIn(const QString &argsLine);
};
#endif // INFO_H #endif // INFO_H

View File

@ -71,4 +71,7 @@ set or view the maximum amount of lines of text that can be displayed in this ap
to set this limit or leave it out to display what the limit is currently set at. this has a minimum value \ to set this limit or leave it out to display what the limit is currently set at. this has a minimum value \
of 50 and a maxmum of 100000." of 50 and a maxmum of 100000."
#define TXT_ListCmds "\
list all commands currently available for runnning (host and client)."
#endif // LONG_TXT_H #endif // LONG_TXT_H

View File

@ -70,12 +70,13 @@
#define DEFAULT_HIST_LIMIT 100 #define DEFAULT_HIST_LIMIT 100
#define DEFAULT_MAX_LINES 1000 #define DEFAULT_MAX_LINES 1000
#define RDBUFF 16777215 #define RDBUFF 16777215
#define DEFAULT_PORT 35516
#define TXT_CODEC "UTF-16LE" #define TXT_CODEC "UTF-16LE"
#define BOOKMARK_FOLDER "bookmarks" #define BOOKMARK_FOLDER "bookmarks"
#define CONFIG_FILENAME "config_v3.json" #define CONFIG_FILENAME "config_v3.json"
#define APP_NAME "Cmdr" #define APP_NAME "Cmdr"
#define APP_TARGET "cmdr" #define APP_TARGET "cmdr"
#define APP_VERSION "3.0" #define APP_VERSION "3.1"
enum TypeID : quint8 enum TypeID : quint8
{ {

View File

@ -118,6 +118,7 @@ int main(int argc, char *argv[])
new SetFont(&app); new SetFont(&app);
new SetMaxLines(&app); new SetMaxLines(&app);
new Genfile(&app); new Genfile(&app);
new ListCmds(&app);
setupClientCmds(); setupClientCmds();
setupCmdLine(); setupCmdLine();