Qt Number Generator v2 Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)GUI Number Generator in QT C++Random Number Generator ClassTrying to find a good design for reading in values of different types from a fileOptimize random number generatorRandom number generator initialisationSimple random generatorRandom number generator in C#Generate cryptographically secure random numbers in a specific rangeC++ Random Phone Number GeneratorQuantum random number generatorGUI Number Generator in QT C++

Passing functions in C++

Roughly how much would it cost to hire a team of dwarves to build a home into a mountainside?

Animated film about a society's offering for gods

How to retrograde a note sequence in Finale?

Replacing HDD with SSD; what about non-APFS/APFS?

Can a 1st-level character have an ability score above 18?

What is the electric potential inside a point charge?

Interesting examples of non-locally compact topological groups

Is there a documented rationale why the House Ways and Means chairman can demand tax info?

A constraint that implies convexity

How to dynamically generate the hash value of a file while it gets downloaded from any website?

Active filter with series inductor and resistor - do these exist?

Stars Make Stars

How to select 3,000 out of 10,000 files in file manager?

Is it possible to ask for a hotel room without minibar/extra services?

The following signatures were invalid: EXPKEYSIG 1397BC53640DB551

Split bolt connection. Wire direction

Am I ethically obligated to go into work on an off day if the reason is sudden?

Dead sea in the midrashim

How does modal jazz use chord progressions?

Limit for e and 1/e

Writing Thesis: Copying from published papers

How to market an anarchic city as a tourism spot to people living in civilized areas?

When is phishing education going too far?



Qt Number Generator v2



Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern)GUI Number Generator in QT C++Random Number Generator ClassTrying to find a good design for reading in values of different types from a fileOptimize random number generatorRandom number generator initialisationSimple random generatorRandom number generator in C#Generate cryptographically secure random numbers in a specific rangeC++ Random Phone Number GeneratorQuantum random number generatorGUI Number Generator in QT C++



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








5












$begingroup$


Link to the old question.



I tried to learn some new things from the answers and here's what I did:



  1. Used Qt Designer so that in Config.h, all member variables and widget positioning are gone

  2. User can't set the lower bound higher than the upper and vice versa

  3. Replaced obsolete qrand with generators from the C++11 <random> library

  4. Used the Qt5 version of connect

  5. Better UI with more options

I like code which can be read as plain English text, that's why I made functions such as _removeLastChar or _correctInputParameters which are basically one-liners but, for me, improve readability a lot.



Code-review IMHO taught me the most about code quality that is why I am asking this "new" version.



Screenshot



generator.h



#ifndef GENERATOR_H
#define GENERATOR_H

#include <QMainWindow>
class QSpinBox;
namespace Ui
class Generator;


class Generator : public QMainWindow

Q_OBJECT

public:
explicit Generator(QWidget *parent = nullptr);
~Generator();

public slots:
void generateNumber();
void clear();
void saveToFile();
void setMinValue(int);
void setMaxValue(int);
private:
Ui::Generator *ui;
qint32 _generateNumber();
QString _getSeparator();
QString _nums;
bool _correctInputParameters();
bool _oneLineOutput();
void _generateNumbers( int from, int to, bool random );
void _removeLastChar( QString& string );
;

#endif // GENERATOR_H


generator.cpp



#include "generator.h"
#include "ui_generator.h"
#include <random>
#include <iostream>
#include <QMessageBox>
#include <QTextStream>
#include <QFileDialog>
Generator::Generator(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::Generator)

ui->setupUi(this);
connect(ui->generateButton, &QPushButton::clicked, this, &Generator::generateNumber);
connect(ui->clearButton, &QPushButton::clicked, this, &Generator::clear);
connect(ui->saveButton, &QPushButton::clicked, this, &Generator::saveToFile);
connect(ui->exitButton, &QPushButton::clicked, this, &QApplication::exit);
connect(ui->minimumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMinValue);
connect(ui->maximumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMaxValue);


void Generator::generateNumber()
clear();
int numbersCount = ui->numbers->value ();
_nums = "";
// random numbers
if ( ui->random->isChecked () )
_generateNumbers (0, numbersCount, true);

// sequential numbers
else
int lower = ui->minimumSpinBox->value ();
int upper = ui->maximumSpinBox->value ();
_generateNumbers (lower, upper + 1, false);

ui->textEdit->setText (_nums);


void Generator::_generateNumbers( int low, int high, bool random )

QString separator = _getSeparator();

for ( qint32 i = low; i < high; ++i )
if ( random ) // random
_nums += QString::number ( _generateNumber () );

else // sequential
_nums += QString::number( i );


_nums += separator;

// output into multiple lines
if ( !_oneLineOutput () )
_nums += "n";


// get rid of the last separator char
if ( _oneLineOutput () && separator != "" ) _removeLastChar(_nums);


void Generator::saveToFile ()
QString filename = QFileDialog::getSaveFileName (this,
tr("Save numbers"), "",
tr("Text file (*.txt);;All Files(*)"));
if ( filename.isEmpty () ) return;
QFile output( filename );

if ( !output.open(QIODevice::WriteOnly

qint32 Generator::_generateNumber()
std::random_device rd;
std::default_random_engine eng(rd());
std::uniform_int_distribution< qint32 > distr( ui->minimumSpinBox->value (),
ui->maximumSpinBox->value () );
return distr(eng);


QString Generator::_getSeparator()
auto separator = ui->separator->currentText();
if ( separator == "(space)" ) return " ";
if ( separator == "(nothing)" ) return "";
return separator;

void Generator::setMinValue( int newValue )
auto maxValue = ui->maximumSpinBox->value ();
if ( newValue > maxValue ) ui->minimumSpinBox->setValue ( maxValue );


void Generator::setMaxValue ( int newValue )
auto minValue = ui->minimumSpinBox->value ();
if ( newValue < minValue ) ui->maximumSpinBox->setValue (minValue);


void Generator::clear ()
ui->textEdit->clear ();


void Generator::_removeLastChar( QString &string )
string.remove ( string.size () - 1, 1 );


bool Generator::_correctInputParameters()
return ui->minimumSpinBox->value () <= ui->maximumSpinBox->value ();


bool Generator::_oneLineOutput()
return ui->oneLine->isChecked ();


Generator::~Generator()
delete ui;










share|improve this question









New contributor




sliziky is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.







$endgroup$


















    5












    $begingroup$


    Link to the old question.



    I tried to learn some new things from the answers and here's what I did:



    1. Used Qt Designer so that in Config.h, all member variables and widget positioning are gone

    2. User can't set the lower bound higher than the upper and vice versa

    3. Replaced obsolete qrand with generators from the C++11 <random> library

    4. Used the Qt5 version of connect

    5. Better UI with more options

    I like code which can be read as plain English text, that's why I made functions such as _removeLastChar or _correctInputParameters which are basically one-liners but, for me, improve readability a lot.



    Code-review IMHO taught me the most about code quality that is why I am asking this "new" version.



    Screenshot



    generator.h



    #ifndef GENERATOR_H
    #define GENERATOR_H

    #include <QMainWindow>
    class QSpinBox;
    namespace Ui
    class Generator;


    class Generator : public QMainWindow

    Q_OBJECT

    public:
    explicit Generator(QWidget *parent = nullptr);
    ~Generator();

    public slots:
    void generateNumber();
    void clear();
    void saveToFile();
    void setMinValue(int);
    void setMaxValue(int);
    private:
    Ui::Generator *ui;
    qint32 _generateNumber();
    QString _getSeparator();
    QString _nums;
    bool _correctInputParameters();
    bool _oneLineOutput();
    void _generateNumbers( int from, int to, bool random );
    void _removeLastChar( QString& string );
    ;

    #endif // GENERATOR_H


    generator.cpp



    #include "generator.h"
    #include "ui_generator.h"
    #include <random>
    #include <iostream>
    #include <QMessageBox>
    #include <QTextStream>
    #include <QFileDialog>
    Generator::Generator(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::Generator)

    ui->setupUi(this);
    connect(ui->generateButton, &QPushButton::clicked, this, &Generator::generateNumber);
    connect(ui->clearButton, &QPushButton::clicked, this, &Generator::clear);
    connect(ui->saveButton, &QPushButton::clicked, this, &Generator::saveToFile);
    connect(ui->exitButton, &QPushButton::clicked, this, &QApplication::exit);
    connect(ui->minimumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMinValue);
    connect(ui->maximumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMaxValue);


    void Generator::generateNumber()
    clear();
    int numbersCount = ui->numbers->value ();
    _nums = "";
    // random numbers
    if ( ui->random->isChecked () )
    _generateNumbers (0, numbersCount, true);

    // sequential numbers
    else
    int lower = ui->minimumSpinBox->value ();
    int upper = ui->maximumSpinBox->value ();
    _generateNumbers (lower, upper + 1, false);

    ui->textEdit->setText (_nums);


    void Generator::_generateNumbers( int low, int high, bool random )

    QString separator = _getSeparator();

    for ( qint32 i = low; i < high; ++i )
    if ( random ) // random
    _nums += QString::number ( _generateNumber () );

    else // sequential
    _nums += QString::number( i );


    _nums += separator;

    // output into multiple lines
    if ( !_oneLineOutput () )
    _nums += "n";


    // get rid of the last separator char
    if ( _oneLineOutput () && separator != "" ) _removeLastChar(_nums);


    void Generator::saveToFile ()
    QString filename = QFileDialog::getSaveFileName (this,
    tr("Save numbers"), "",
    tr("Text file (*.txt);;All Files(*)"));
    if ( filename.isEmpty () ) return;
    QFile output( filename );

    if ( !output.open(QIODevice::WriteOnly

    qint32 Generator::_generateNumber()
    std::random_device rd;
    std::default_random_engine eng(rd());
    std::uniform_int_distribution< qint32 > distr( ui->minimumSpinBox->value (),
    ui->maximumSpinBox->value () );
    return distr(eng);


    QString Generator::_getSeparator()
    auto separator = ui->separator->currentText();
    if ( separator == "(space)" ) return " ";
    if ( separator == "(nothing)" ) return "";
    return separator;

    void Generator::setMinValue( int newValue )
    auto maxValue = ui->maximumSpinBox->value ();
    if ( newValue > maxValue ) ui->minimumSpinBox->setValue ( maxValue );


    void Generator::setMaxValue ( int newValue )
    auto minValue = ui->minimumSpinBox->value ();
    if ( newValue < minValue ) ui->maximumSpinBox->setValue (minValue);


    void Generator::clear ()
    ui->textEdit->clear ();


    void Generator::_removeLastChar( QString &string )
    string.remove ( string.size () - 1, 1 );


    bool Generator::_correctInputParameters()
    return ui->minimumSpinBox->value () <= ui->maximumSpinBox->value ();


    bool Generator::_oneLineOutput()
    return ui->oneLine->isChecked ();


    Generator::~Generator()
    delete ui;










    share|improve this question









    New contributor




    sliziky is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.







    $endgroup$














      5












      5








      5





      $begingroup$


      Link to the old question.



      I tried to learn some new things from the answers and here's what I did:



      1. Used Qt Designer so that in Config.h, all member variables and widget positioning are gone

      2. User can't set the lower bound higher than the upper and vice versa

      3. Replaced obsolete qrand with generators from the C++11 <random> library

      4. Used the Qt5 version of connect

      5. Better UI with more options

      I like code which can be read as plain English text, that's why I made functions such as _removeLastChar or _correctInputParameters which are basically one-liners but, for me, improve readability a lot.



      Code-review IMHO taught me the most about code quality that is why I am asking this "new" version.



      Screenshot



      generator.h



      #ifndef GENERATOR_H
      #define GENERATOR_H

      #include <QMainWindow>
      class QSpinBox;
      namespace Ui
      class Generator;


      class Generator : public QMainWindow

      Q_OBJECT

      public:
      explicit Generator(QWidget *parent = nullptr);
      ~Generator();

      public slots:
      void generateNumber();
      void clear();
      void saveToFile();
      void setMinValue(int);
      void setMaxValue(int);
      private:
      Ui::Generator *ui;
      qint32 _generateNumber();
      QString _getSeparator();
      QString _nums;
      bool _correctInputParameters();
      bool _oneLineOutput();
      void _generateNumbers( int from, int to, bool random );
      void _removeLastChar( QString& string );
      ;

      #endif // GENERATOR_H


      generator.cpp



      #include "generator.h"
      #include "ui_generator.h"
      #include <random>
      #include <iostream>
      #include <QMessageBox>
      #include <QTextStream>
      #include <QFileDialog>
      Generator::Generator(QWidget *parent)
      : QMainWindow(parent)
      , ui(new Ui::Generator)

      ui->setupUi(this);
      connect(ui->generateButton, &QPushButton::clicked, this, &Generator::generateNumber);
      connect(ui->clearButton, &QPushButton::clicked, this, &Generator::clear);
      connect(ui->saveButton, &QPushButton::clicked, this, &Generator::saveToFile);
      connect(ui->exitButton, &QPushButton::clicked, this, &QApplication::exit);
      connect(ui->minimumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMinValue);
      connect(ui->maximumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMaxValue);


      void Generator::generateNumber()
      clear();
      int numbersCount = ui->numbers->value ();
      _nums = "";
      // random numbers
      if ( ui->random->isChecked () )
      _generateNumbers (0, numbersCount, true);

      // sequential numbers
      else
      int lower = ui->minimumSpinBox->value ();
      int upper = ui->maximumSpinBox->value ();
      _generateNumbers (lower, upper + 1, false);

      ui->textEdit->setText (_nums);


      void Generator::_generateNumbers( int low, int high, bool random )

      QString separator = _getSeparator();

      for ( qint32 i = low; i < high; ++i )
      if ( random ) // random
      _nums += QString::number ( _generateNumber () );

      else // sequential
      _nums += QString::number( i );


      _nums += separator;

      // output into multiple lines
      if ( !_oneLineOutput () )
      _nums += "n";


      // get rid of the last separator char
      if ( _oneLineOutput () && separator != "" ) _removeLastChar(_nums);


      void Generator::saveToFile ()
      QString filename = QFileDialog::getSaveFileName (this,
      tr("Save numbers"), "",
      tr("Text file (*.txt);;All Files(*)"));
      if ( filename.isEmpty () ) return;
      QFile output( filename );

      if ( !output.open(QIODevice::WriteOnly

      qint32 Generator::_generateNumber()
      std::random_device rd;
      std::default_random_engine eng(rd());
      std::uniform_int_distribution< qint32 > distr( ui->minimumSpinBox->value (),
      ui->maximumSpinBox->value () );
      return distr(eng);


      QString Generator::_getSeparator()
      auto separator = ui->separator->currentText();
      if ( separator == "(space)" ) return " ";
      if ( separator == "(nothing)" ) return "";
      return separator;

      void Generator::setMinValue( int newValue )
      auto maxValue = ui->maximumSpinBox->value ();
      if ( newValue > maxValue ) ui->minimumSpinBox->setValue ( maxValue );


      void Generator::setMaxValue ( int newValue )
      auto minValue = ui->minimumSpinBox->value ();
      if ( newValue < minValue ) ui->maximumSpinBox->setValue (minValue);


      void Generator::clear ()
      ui->textEdit->clear ();


      void Generator::_removeLastChar( QString &string )
      string.remove ( string.size () - 1, 1 );


      bool Generator::_correctInputParameters()
      return ui->minimumSpinBox->value () <= ui->maximumSpinBox->value ();


      bool Generator::_oneLineOutput()
      return ui->oneLine->isChecked ();


      Generator::~Generator()
      delete ui;










      share|improve this question









      New contributor




      sliziky is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.







      $endgroup$




      Link to the old question.



      I tried to learn some new things from the answers and here's what I did:



      1. Used Qt Designer so that in Config.h, all member variables and widget positioning are gone

      2. User can't set the lower bound higher than the upper and vice versa

      3. Replaced obsolete qrand with generators from the C++11 <random> library

      4. Used the Qt5 version of connect

      5. Better UI with more options

      I like code which can be read as plain English text, that's why I made functions such as _removeLastChar or _correctInputParameters which are basically one-liners but, for me, improve readability a lot.



      Code-review IMHO taught me the most about code quality that is why I am asking this "new" version.



      Screenshot



      generator.h



      #ifndef GENERATOR_H
      #define GENERATOR_H

      #include <QMainWindow>
      class QSpinBox;
      namespace Ui
      class Generator;


      class Generator : public QMainWindow

      Q_OBJECT

      public:
      explicit Generator(QWidget *parent = nullptr);
      ~Generator();

      public slots:
      void generateNumber();
      void clear();
      void saveToFile();
      void setMinValue(int);
      void setMaxValue(int);
      private:
      Ui::Generator *ui;
      qint32 _generateNumber();
      QString _getSeparator();
      QString _nums;
      bool _correctInputParameters();
      bool _oneLineOutput();
      void _generateNumbers( int from, int to, bool random );
      void _removeLastChar( QString& string );
      ;

      #endif // GENERATOR_H


      generator.cpp



      #include "generator.h"
      #include "ui_generator.h"
      #include <random>
      #include <iostream>
      #include <QMessageBox>
      #include <QTextStream>
      #include <QFileDialog>
      Generator::Generator(QWidget *parent)
      : QMainWindow(parent)
      , ui(new Ui::Generator)

      ui->setupUi(this);
      connect(ui->generateButton, &QPushButton::clicked, this, &Generator::generateNumber);
      connect(ui->clearButton, &QPushButton::clicked, this, &Generator::clear);
      connect(ui->saveButton, &QPushButton::clicked, this, &Generator::saveToFile);
      connect(ui->exitButton, &QPushButton::clicked, this, &QApplication::exit);
      connect(ui->minimumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMinValue);
      connect(ui->maximumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMaxValue);


      void Generator::generateNumber()
      clear();
      int numbersCount = ui->numbers->value ();
      _nums = "";
      // random numbers
      if ( ui->random->isChecked () )
      _generateNumbers (0, numbersCount, true);

      // sequential numbers
      else
      int lower = ui->minimumSpinBox->value ();
      int upper = ui->maximumSpinBox->value ();
      _generateNumbers (lower, upper + 1, false);

      ui->textEdit->setText (_nums);


      void Generator::_generateNumbers( int low, int high, bool random )

      QString separator = _getSeparator();

      for ( qint32 i = low; i < high; ++i )
      if ( random ) // random
      _nums += QString::number ( _generateNumber () );

      else // sequential
      _nums += QString::number( i );


      _nums += separator;

      // output into multiple lines
      if ( !_oneLineOutput () )
      _nums += "n";


      // get rid of the last separator char
      if ( _oneLineOutput () && separator != "" ) _removeLastChar(_nums);


      void Generator::saveToFile ()
      QString filename = QFileDialog::getSaveFileName (this,
      tr("Save numbers"), "",
      tr("Text file (*.txt);;All Files(*)"));
      if ( filename.isEmpty () ) return;
      QFile output( filename );

      if ( !output.open(QIODevice::WriteOnly

      qint32 Generator::_generateNumber()
      std::random_device rd;
      std::default_random_engine eng(rd());
      std::uniform_int_distribution< qint32 > distr( ui->minimumSpinBox->value (),
      ui->maximumSpinBox->value () );
      return distr(eng);


      QString Generator::_getSeparator()
      auto separator = ui->separator->currentText();
      if ( separator == "(space)" ) return " ";
      if ( separator == "(nothing)" ) return "";
      return separator;

      void Generator::setMinValue( int newValue )
      auto maxValue = ui->maximumSpinBox->value ();
      if ( newValue > maxValue ) ui->minimumSpinBox->setValue ( maxValue );


      void Generator::setMaxValue ( int newValue )
      auto minValue = ui->minimumSpinBox->value ();
      if ( newValue < minValue ) ui->maximumSpinBox->setValue (minValue);


      void Generator::clear ()
      ui->textEdit->clear ();


      void Generator::_removeLastChar( QString &string )
      string.remove ( string.size () - 1, 1 );


      bool Generator::_correctInputParameters()
      return ui->minimumSpinBox->value () <= ui->maximumSpinBox->value ();


      bool Generator::_oneLineOutput()
      return ui->oneLine->isChecked ();


      Generator::~Generator()
      delete ui;







      c++ c++11 random gui qt






      share|improve this question









      New contributor




      sliziky is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      sliziky is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited 2 hours ago









      TrebledJ

      1505




      1505






      New contributor




      sliziky is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 9 hours ago









      slizikysliziky

      553




      553




      New contributor




      sliziky is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      sliziky is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      sliziky is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.




















          1 Answer
          1






          active

          oldest

          votes


















          3












          $begingroup$

          Seems like you've made a lot of improvements since your previous post! Let's get into the review!



          1. General Overview



          a. Use the on_<objectName>_<signal> Naming Scheme for Slots



          This naming scheme tells the moc to automatically connect a slot with the corresponding <signal> of <objectName> from the UI. We then don't need to call connect(...), saving us a few lines of code.



          If we take a look at the clearButton UI object, we can get this auto-connect behaviour by renaming the clear method to on_clearButton_clicked. The implementation doesn't change, only the symbol.



          This process of pinpointing the correct slot name is automated from Design mode. First, right-click the object itself or the listing on the object-class tree. Then select the signal to connect and the slot to go to. Qt will automatically generate the on_clearButton_clicked slot in the header and source files (if it doesn't exist yet).



          Right-click on the Clear button and select Go to slot...
          Right-click on your Clear button to bring up the context menu and select Go to slot...



          enter image description here
          Choose the clicked() signal and click OK.



          Now you no longer need manually connect with connect(...). You can apply this to generateButton, clearButton, saveButton, minimumSpinBox, and maximumSpinBox. Yay, 5 less lines of code! 5 less worries!



          (To be clear, static_cast<void (QSpinBox::*)(int)> isn't needed for minimumSpinBox, and maximumSpinBox as the correct overload can be automatically deduced.)



          Also note that this naming scheme doesn't have to be used for every slot – it is primarily used for those slots which have a corresponding signal from the UI.



          b. Consistency in Order of Methods in Header and Source Files



          In your header file, the first four function-like declarations are



          public:
          explicit Generator(QWidget *parent = nullptr);
          ~Generator();
          public slots:
          void generateNumber();
          void clear();


          However, in your source file, the definition for the destructor comes last. This harms readability. Most readers may be expecting the same ordering of methods in both header and source files. Does this mean the header file should conform to the ordering of the source file? Something like below perhaps?



          public:
          explicit Generator(QWidget *parent = nullptr);
          public slots:
          void generateNumber();
          void clear();
          public:
          ~Generator();


          Nawww, the source file should conform to the header file. Please, please, please; if you declare the destructor right after the constructor, define the destructor right after the constructor.



          Generator::Generator(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::Generator)

          ui->setupUi(this);
          connect(ui->generateButton, &QPushButton::clicked, this, &Generator::generateNumber);
          connect(ui->clearButton, &QPushButton::clicked, this, &Generator::clear);
          connect(ui->saveButton, &QPushButton::clicked, this, &Generator::saveToFile);
          connect(ui->exitButton, &QPushButton::clicked, this, &QApplication::exit);
          connect(ui->minimumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMinValue);
          connect(ui->maximumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMaxValue);


          Generator::~Generator()
          delete ui;


          // other methods
          // ...


          c. Naming



          i. _generateNumbers(int ?, int ?, bool random)



          A minor issue. You have



          void _generateNumbers( int from, int to, bool random );


          in your header file but



          void Generator::_generateNumbers( int low, int high, bool random ) {


          in your source code. Choose either from/to or low/high, but not both.



          ii. _correctInputParameters and oneLineOutput



          For methods that return bool (also known as predicates), consider starting the method with is or has.



          bool _hasCorrectInputParameters();
          bool _isOneLineOutput();


          Helps with readability. We don't need any special guesswork to infer that these will return bool.



          2. Logic



          The logic and program flow seems a tad messy, let's try cleaning it up!



          a. clear()



          What should this clear? Only the text-edit? I'd clear _nums as well.



          void Generator::clear() 
          ui->textEdit->clear();
          _nums.clear();



          The last thing we want is to have the clear method clear only the gui and leave the variable sitting. Clear everything it all at once! Doing so allows us to pinpoint bugs easier – we don't have to spend 30 minutes digging through the entire code to find a lone _nums = "" placed wrongly.



          b. generateNumber and _generateNumbers and _generateNumber



          First off, these methods could do with better naming. As soon as I type generate, the IDE completer will show these three methods and it all suddenly becomes ambiguous. Be specific with what each method does.




          • _generateNumber only generates random numbers, so change it to _generateRandomNumber.


          • generateNumber handles the button click, so follow the first section of this answer and change it to on_generateButton_clicked.


          • _generateNumbers is a fine name as it is.

          Down to the logic. It doesn't really make sense to retrieve values of minimumSpinBox and maximumSpinBox in two places (one, in generateNumber, under the else branch; and two, in _generateNumber). Retrieve it once, then pass it accordingly. By the same principle, since only the random option needs int numbersCount = ui->numbers->value();, this should be placed in _generateNumbers instead.



          void Generator::generateNumber() 
          clear();
          // _nums = ""; // moved to clear(); same as _nums.clear()

          int low = ui->minimumSpinBox->value(); // retrieve values from spinboxes ONCE
          int high = ui->maximumSpinBox->value();

          _generateNumbers(low, high+1, ui->random->isChecked()); // universal, no need for if-else

          ui->textEdit->setText(_nums);



          This also means changing _generateNumber to accept parameters so that we can later pass the low and high in generateNumber:



          qint32 Generator::_generateNumber(int low, int high) 
          std::random_device rd;
          std::default_random_engine eng(rd());
          std::uniform_int_distribution<qint32> distr(low, high);
          return distr(eng);



          Currently, _generateNumbers serves two purposes: generating random numbers and generating sequential numbers. However, the arguments used are for completely different purposes, which is... meh... until their names contradict with their purpose which merits another meh. This seems like a big red sign to me:



          if ( ui->random->isChecked () ) 
          _generateNumbers (0, numbersCount, true); // low = 0, high = numbersCount ?



          Does this use case not imply that the generated numbers should be between 0 and numbersCount? Apparently not... Apparently, low and high in that context means to generate high – low number of values.



          Since the purposes and use cases are different, it only makes sense to have different implementations, so branch your if-else well ahead of the for-loop(s).



          void Generator::_generateNumbers( int low, int high, bool random ) 

          QString separator = _getSeparator();

          if (random)
          int numbersCount = ui->numbers->value();
          // generate random numbers between low and high
          // for (int i = 0; i < numbersCount; i++)
          // ...
          else
          // generate random numbers between low and high
          // ...


          // get rid of the last separator char
          if ( _oneLineOutput () && separator != "" ) _removeLastChar(_nums);



          3. UI



          On the UI side, I'd consider removing some borders – they do get in the way, especially the ones around Generate Numbers and the ones around your four buttons.



          You should also consider disabling the How many numbers spinbox if the selected number pattern is Sequential as the two are mutually exclusive options.



          But then, you could also consider the case where the user selects Sequential and provides a from-value and how-many-numbers-value but doesn't provide a to-value. Sounds like you could make this a third Numbers option: Sequential-n.



          It's unfortunate that we don't get the .ui to play around with, but nonetheless, it looks stunning and functional from afar. :-)






          share|improve this answer










          New contributor




          TrebledJ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.






          $endgroup$








          • 2




            $begingroup$
            Welcome to Code Review! Nice job, first post or not.
            $endgroup$
            – greybeard
            3 hours ago










          • $begingroup$
            I realised I missed out a bunch of stuff on my first read. Had to read the code a third time to actually see a large proportion of the inherent problems. :P
            $endgroup$
            – TrebledJ
            3 hours ago











          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );






          sliziky is a new contributor. Be nice, and check out our Code of Conduct.









          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217431%2fqt-number-generator-v2%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          3












          $begingroup$

          Seems like you've made a lot of improvements since your previous post! Let's get into the review!



          1. General Overview



          a. Use the on_<objectName>_<signal> Naming Scheme for Slots



          This naming scheme tells the moc to automatically connect a slot with the corresponding <signal> of <objectName> from the UI. We then don't need to call connect(...), saving us a few lines of code.



          If we take a look at the clearButton UI object, we can get this auto-connect behaviour by renaming the clear method to on_clearButton_clicked. The implementation doesn't change, only the symbol.



          This process of pinpointing the correct slot name is automated from Design mode. First, right-click the object itself or the listing on the object-class tree. Then select the signal to connect and the slot to go to. Qt will automatically generate the on_clearButton_clicked slot in the header and source files (if it doesn't exist yet).



          Right-click on the Clear button and select Go to slot...
          Right-click on your Clear button to bring up the context menu and select Go to slot...



          enter image description here
          Choose the clicked() signal and click OK.



          Now you no longer need manually connect with connect(...). You can apply this to generateButton, clearButton, saveButton, minimumSpinBox, and maximumSpinBox. Yay, 5 less lines of code! 5 less worries!



          (To be clear, static_cast<void (QSpinBox::*)(int)> isn't needed for minimumSpinBox, and maximumSpinBox as the correct overload can be automatically deduced.)



          Also note that this naming scheme doesn't have to be used for every slot – it is primarily used for those slots which have a corresponding signal from the UI.



          b. Consistency in Order of Methods in Header and Source Files



          In your header file, the first four function-like declarations are



          public:
          explicit Generator(QWidget *parent = nullptr);
          ~Generator();
          public slots:
          void generateNumber();
          void clear();


          However, in your source file, the definition for the destructor comes last. This harms readability. Most readers may be expecting the same ordering of methods in both header and source files. Does this mean the header file should conform to the ordering of the source file? Something like below perhaps?



          public:
          explicit Generator(QWidget *parent = nullptr);
          public slots:
          void generateNumber();
          void clear();
          public:
          ~Generator();


          Nawww, the source file should conform to the header file. Please, please, please; if you declare the destructor right after the constructor, define the destructor right after the constructor.



          Generator::Generator(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::Generator)

          ui->setupUi(this);
          connect(ui->generateButton, &QPushButton::clicked, this, &Generator::generateNumber);
          connect(ui->clearButton, &QPushButton::clicked, this, &Generator::clear);
          connect(ui->saveButton, &QPushButton::clicked, this, &Generator::saveToFile);
          connect(ui->exitButton, &QPushButton::clicked, this, &QApplication::exit);
          connect(ui->minimumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMinValue);
          connect(ui->maximumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMaxValue);


          Generator::~Generator()
          delete ui;


          // other methods
          // ...


          c. Naming



          i. _generateNumbers(int ?, int ?, bool random)



          A minor issue. You have



          void _generateNumbers( int from, int to, bool random );


          in your header file but



          void Generator::_generateNumbers( int low, int high, bool random ) {


          in your source code. Choose either from/to or low/high, but not both.



          ii. _correctInputParameters and oneLineOutput



          For methods that return bool (also known as predicates), consider starting the method with is or has.



          bool _hasCorrectInputParameters();
          bool _isOneLineOutput();


          Helps with readability. We don't need any special guesswork to infer that these will return bool.



          2. Logic



          The logic and program flow seems a tad messy, let's try cleaning it up!



          a. clear()



          What should this clear? Only the text-edit? I'd clear _nums as well.



          void Generator::clear() 
          ui->textEdit->clear();
          _nums.clear();



          The last thing we want is to have the clear method clear only the gui and leave the variable sitting. Clear everything it all at once! Doing so allows us to pinpoint bugs easier – we don't have to spend 30 minutes digging through the entire code to find a lone _nums = "" placed wrongly.



          b. generateNumber and _generateNumbers and _generateNumber



          First off, these methods could do with better naming. As soon as I type generate, the IDE completer will show these three methods and it all suddenly becomes ambiguous. Be specific with what each method does.




          • _generateNumber only generates random numbers, so change it to _generateRandomNumber.


          • generateNumber handles the button click, so follow the first section of this answer and change it to on_generateButton_clicked.


          • _generateNumbers is a fine name as it is.

          Down to the logic. It doesn't really make sense to retrieve values of minimumSpinBox and maximumSpinBox in two places (one, in generateNumber, under the else branch; and two, in _generateNumber). Retrieve it once, then pass it accordingly. By the same principle, since only the random option needs int numbersCount = ui->numbers->value();, this should be placed in _generateNumbers instead.



          void Generator::generateNumber() 
          clear();
          // _nums = ""; // moved to clear(); same as _nums.clear()

          int low = ui->minimumSpinBox->value(); // retrieve values from spinboxes ONCE
          int high = ui->maximumSpinBox->value();

          _generateNumbers(low, high+1, ui->random->isChecked()); // universal, no need for if-else

          ui->textEdit->setText(_nums);



          This also means changing _generateNumber to accept parameters so that we can later pass the low and high in generateNumber:



          qint32 Generator::_generateNumber(int low, int high) 
          std::random_device rd;
          std::default_random_engine eng(rd());
          std::uniform_int_distribution<qint32> distr(low, high);
          return distr(eng);



          Currently, _generateNumbers serves two purposes: generating random numbers and generating sequential numbers. However, the arguments used are for completely different purposes, which is... meh... until their names contradict with their purpose which merits another meh. This seems like a big red sign to me:



          if ( ui->random->isChecked () ) 
          _generateNumbers (0, numbersCount, true); // low = 0, high = numbersCount ?



          Does this use case not imply that the generated numbers should be between 0 and numbersCount? Apparently not... Apparently, low and high in that context means to generate high – low number of values.



          Since the purposes and use cases are different, it only makes sense to have different implementations, so branch your if-else well ahead of the for-loop(s).



          void Generator::_generateNumbers( int low, int high, bool random ) 

          QString separator = _getSeparator();

          if (random)
          int numbersCount = ui->numbers->value();
          // generate random numbers between low and high
          // for (int i = 0; i < numbersCount; i++)
          // ...
          else
          // generate random numbers between low and high
          // ...


          // get rid of the last separator char
          if ( _oneLineOutput () && separator != "" ) _removeLastChar(_nums);



          3. UI



          On the UI side, I'd consider removing some borders – they do get in the way, especially the ones around Generate Numbers and the ones around your four buttons.



          You should also consider disabling the How many numbers spinbox if the selected number pattern is Sequential as the two are mutually exclusive options.



          But then, you could also consider the case where the user selects Sequential and provides a from-value and how-many-numbers-value but doesn't provide a to-value. Sounds like you could make this a third Numbers option: Sequential-n.



          It's unfortunate that we don't get the .ui to play around with, but nonetheless, it looks stunning and functional from afar. :-)






          share|improve this answer










          New contributor




          TrebledJ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.






          $endgroup$








          • 2




            $begingroup$
            Welcome to Code Review! Nice job, first post or not.
            $endgroup$
            – greybeard
            3 hours ago










          • $begingroup$
            I realised I missed out a bunch of stuff on my first read. Had to read the code a third time to actually see a large proportion of the inherent problems. :P
            $endgroup$
            – TrebledJ
            3 hours ago















          3












          $begingroup$

          Seems like you've made a lot of improvements since your previous post! Let's get into the review!



          1. General Overview



          a. Use the on_<objectName>_<signal> Naming Scheme for Slots



          This naming scheme tells the moc to automatically connect a slot with the corresponding <signal> of <objectName> from the UI. We then don't need to call connect(...), saving us a few lines of code.



          If we take a look at the clearButton UI object, we can get this auto-connect behaviour by renaming the clear method to on_clearButton_clicked. The implementation doesn't change, only the symbol.



          This process of pinpointing the correct slot name is automated from Design mode. First, right-click the object itself or the listing on the object-class tree. Then select the signal to connect and the slot to go to. Qt will automatically generate the on_clearButton_clicked slot in the header and source files (if it doesn't exist yet).



          Right-click on the Clear button and select Go to slot...
          Right-click on your Clear button to bring up the context menu and select Go to slot...



          enter image description here
          Choose the clicked() signal and click OK.



          Now you no longer need manually connect with connect(...). You can apply this to generateButton, clearButton, saveButton, minimumSpinBox, and maximumSpinBox. Yay, 5 less lines of code! 5 less worries!



          (To be clear, static_cast<void (QSpinBox::*)(int)> isn't needed for minimumSpinBox, and maximumSpinBox as the correct overload can be automatically deduced.)



          Also note that this naming scheme doesn't have to be used for every slot – it is primarily used for those slots which have a corresponding signal from the UI.



          b. Consistency in Order of Methods in Header and Source Files



          In your header file, the first four function-like declarations are



          public:
          explicit Generator(QWidget *parent = nullptr);
          ~Generator();
          public slots:
          void generateNumber();
          void clear();


          However, in your source file, the definition for the destructor comes last. This harms readability. Most readers may be expecting the same ordering of methods in both header and source files. Does this mean the header file should conform to the ordering of the source file? Something like below perhaps?



          public:
          explicit Generator(QWidget *parent = nullptr);
          public slots:
          void generateNumber();
          void clear();
          public:
          ~Generator();


          Nawww, the source file should conform to the header file. Please, please, please; if you declare the destructor right after the constructor, define the destructor right after the constructor.



          Generator::Generator(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::Generator)

          ui->setupUi(this);
          connect(ui->generateButton, &QPushButton::clicked, this, &Generator::generateNumber);
          connect(ui->clearButton, &QPushButton::clicked, this, &Generator::clear);
          connect(ui->saveButton, &QPushButton::clicked, this, &Generator::saveToFile);
          connect(ui->exitButton, &QPushButton::clicked, this, &QApplication::exit);
          connect(ui->minimumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMinValue);
          connect(ui->maximumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMaxValue);


          Generator::~Generator()
          delete ui;


          // other methods
          // ...


          c. Naming



          i. _generateNumbers(int ?, int ?, bool random)



          A minor issue. You have



          void _generateNumbers( int from, int to, bool random );


          in your header file but



          void Generator::_generateNumbers( int low, int high, bool random ) {


          in your source code. Choose either from/to or low/high, but not both.



          ii. _correctInputParameters and oneLineOutput



          For methods that return bool (also known as predicates), consider starting the method with is or has.



          bool _hasCorrectInputParameters();
          bool _isOneLineOutput();


          Helps with readability. We don't need any special guesswork to infer that these will return bool.



          2. Logic



          The logic and program flow seems a tad messy, let's try cleaning it up!



          a. clear()



          What should this clear? Only the text-edit? I'd clear _nums as well.



          void Generator::clear() 
          ui->textEdit->clear();
          _nums.clear();



          The last thing we want is to have the clear method clear only the gui and leave the variable sitting. Clear everything it all at once! Doing so allows us to pinpoint bugs easier – we don't have to spend 30 minutes digging through the entire code to find a lone _nums = "" placed wrongly.



          b. generateNumber and _generateNumbers and _generateNumber



          First off, these methods could do with better naming. As soon as I type generate, the IDE completer will show these three methods and it all suddenly becomes ambiguous. Be specific with what each method does.




          • _generateNumber only generates random numbers, so change it to _generateRandomNumber.


          • generateNumber handles the button click, so follow the first section of this answer and change it to on_generateButton_clicked.


          • _generateNumbers is a fine name as it is.

          Down to the logic. It doesn't really make sense to retrieve values of minimumSpinBox and maximumSpinBox in two places (one, in generateNumber, under the else branch; and two, in _generateNumber). Retrieve it once, then pass it accordingly. By the same principle, since only the random option needs int numbersCount = ui->numbers->value();, this should be placed in _generateNumbers instead.



          void Generator::generateNumber() 
          clear();
          // _nums = ""; // moved to clear(); same as _nums.clear()

          int low = ui->minimumSpinBox->value(); // retrieve values from spinboxes ONCE
          int high = ui->maximumSpinBox->value();

          _generateNumbers(low, high+1, ui->random->isChecked()); // universal, no need for if-else

          ui->textEdit->setText(_nums);



          This also means changing _generateNumber to accept parameters so that we can later pass the low and high in generateNumber:



          qint32 Generator::_generateNumber(int low, int high) 
          std::random_device rd;
          std::default_random_engine eng(rd());
          std::uniform_int_distribution<qint32> distr(low, high);
          return distr(eng);



          Currently, _generateNumbers serves two purposes: generating random numbers and generating sequential numbers. However, the arguments used are for completely different purposes, which is... meh... until their names contradict with their purpose which merits another meh. This seems like a big red sign to me:



          if ( ui->random->isChecked () ) 
          _generateNumbers (0, numbersCount, true); // low = 0, high = numbersCount ?



          Does this use case not imply that the generated numbers should be between 0 and numbersCount? Apparently not... Apparently, low and high in that context means to generate high – low number of values.



          Since the purposes and use cases are different, it only makes sense to have different implementations, so branch your if-else well ahead of the for-loop(s).



          void Generator::_generateNumbers( int low, int high, bool random ) 

          QString separator = _getSeparator();

          if (random)
          int numbersCount = ui->numbers->value();
          // generate random numbers between low and high
          // for (int i = 0; i < numbersCount; i++)
          // ...
          else
          // generate random numbers between low and high
          // ...


          // get rid of the last separator char
          if ( _oneLineOutput () && separator != "" ) _removeLastChar(_nums);



          3. UI



          On the UI side, I'd consider removing some borders – they do get in the way, especially the ones around Generate Numbers and the ones around your four buttons.



          You should also consider disabling the How many numbers spinbox if the selected number pattern is Sequential as the two are mutually exclusive options.



          But then, you could also consider the case where the user selects Sequential and provides a from-value and how-many-numbers-value but doesn't provide a to-value. Sounds like you could make this a third Numbers option: Sequential-n.



          It's unfortunate that we don't get the .ui to play around with, but nonetheless, it looks stunning and functional from afar. :-)






          share|improve this answer










          New contributor




          TrebledJ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.






          $endgroup$








          • 2




            $begingroup$
            Welcome to Code Review! Nice job, first post or not.
            $endgroup$
            – greybeard
            3 hours ago










          • $begingroup$
            I realised I missed out a bunch of stuff on my first read. Had to read the code a third time to actually see a large proportion of the inherent problems. :P
            $endgroup$
            – TrebledJ
            3 hours ago













          3












          3








          3





          $begingroup$

          Seems like you've made a lot of improvements since your previous post! Let's get into the review!



          1. General Overview



          a. Use the on_<objectName>_<signal> Naming Scheme for Slots



          This naming scheme tells the moc to automatically connect a slot with the corresponding <signal> of <objectName> from the UI. We then don't need to call connect(...), saving us a few lines of code.



          If we take a look at the clearButton UI object, we can get this auto-connect behaviour by renaming the clear method to on_clearButton_clicked. The implementation doesn't change, only the symbol.



          This process of pinpointing the correct slot name is automated from Design mode. First, right-click the object itself or the listing on the object-class tree. Then select the signal to connect and the slot to go to. Qt will automatically generate the on_clearButton_clicked slot in the header and source files (if it doesn't exist yet).



          Right-click on the Clear button and select Go to slot...
          Right-click on your Clear button to bring up the context menu and select Go to slot...



          enter image description here
          Choose the clicked() signal and click OK.



          Now you no longer need manually connect with connect(...). You can apply this to generateButton, clearButton, saveButton, minimumSpinBox, and maximumSpinBox. Yay, 5 less lines of code! 5 less worries!



          (To be clear, static_cast<void (QSpinBox::*)(int)> isn't needed for minimumSpinBox, and maximumSpinBox as the correct overload can be automatically deduced.)



          Also note that this naming scheme doesn't have to be used for every slot – it is primarily used for those slots which have a corresponding signal from the UI.



          b. Consistency in Order of Methods in Header and Source Files



          In your header file, the first four function-like declarations are



          public:
          explicit Generator(QWidget *parent = nullptr);
          ~Generator();
          public slots:
          void generateNumber();
          void clear();


          However, in your source file, the definition for the destructor comes last. This harms readability. Most readers may be expecting the same ordering of methods in both header and source files. Does this mean the header file should conform to the ordering of the source file? Something like below perhaps?



          public:
          explicit Generator(QWidget *parent = nullptr);
          public slots:
          void generateNumber();
          void clear();
          public:
          ~Generator();


          Nawww, the source file should conform to the header file. Please, please, please; if you declare the destructor right after the constructor, define the destructor right after the constructor.



          Generator::Generator(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::Generator)

          ui->setupUi(this);
          connect(ui->generateButton, &QPushButton::clicked, this, &Generator::generateNumber);
          connect(ui->clearButton, &QPushButton::clicked, this, &Generator::clear);
          connect(ui->saveButton, &QPushButton::clicked, this, &Generator::saveToFile);
          connect(ui->exitButton, &QPushButton::clicked, this, &QApplication::exit);
          connect(ui->minimumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMinValue);
          connect(ui->maximumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMaxValue);


          Generator::~Generator()
          delete ui;


          // other methods
          // ...


          c. Naming



          i. _generateNumbers(int ?, int ?, bool random)



          A minor issue. You have



          void _generateNumbers( int from, int to, bool random );


          in your header file but



          void Generator::_generateNumbers( int low, int high, bool random ) {


          in your source code. Choose either from/to or low/high, but not both.



          ii. _correctInputParameters and oneLineOutput



          For methods that return bool (also known as predicates), consider starting the method with is or has.



          bool _hasCorrectInputParameters();
          bool _isOneLineOutput();


          Helps with readability. We don't need any special guesswork to infer that these will return bool.



          2. Logic



          The logic and program flow seems a tad messy, let's try cleaning it up!



          a. clear()



          What should this clear? Only the text-edit? I'd clear _nums as well.



          void Generator::clear() 
          ui->textEdit->clear();
          _nums.clear();



          The last thing we want is to have the clear method clear only the gui and leave the variable sitting. Clear everything it all at once! Doing so allows us to pinpoint bugs easier – we don't have to spend 30 minutes digging through the entire code to find a lone _nums = "" placed wrongly.



          b. generateNumber and _generateNumbers and _generateNumber



          First off, these methods could do with better naming. As soon as I type generate, the IDE completer will show these three methods and it all suddenly becomes ambiguous. Be specific with what each method does.




          • _generateNumber only generates random numbers, so change it to _generateRandomNumber.


          • generateNumber handles the button click, so follow the first section of this answer and change it to on_generateButton_clicked.


          • _generateNumbers is a fine name as it is.

          Down to the logic. It doesn't really make sense to retrieve values of minimumSpinBox and maximumSpinBox in two places (one, in generateNumber, under the else branch; and two, in _generateNumber). Retrieve it once, then pass it accordingly. By the same principle, since only the random option needs int numbersCount = ui->numbers->value();, this should be placed in _generateNumbers instead.



          void Generator::generateNumber() 
          clear();
          // _nums = ""; // moved to clear(); same as _nums.clear()

          int low = ui->minimumSpinBox->value(); // retrieve values from spinboxes ONCE
          int high = ui->maximumSpinBox->value();

          _generateNumbers(low, high+1, ui->random->isChecked()); // universal, no need for if-else

          ui->textEdit->setText(_nums);



          This also means changing _generateNumber to accept parameters so that we can later pass the low and high in generateNumber:



          qint32 Generator::_generateNumber(int low, int high) 
          std::random_device rd;
          std::default_random_engine eng(rd());
          std::uniform_int_distribution<qint32> distr(low, high);
          return distr(eng);



          Currently, _generateNumbers serves two purposes: generating random numbers and generating sequential numbers. However, the arguments used are for completely different purposes, which is... meh... until their names contradict with their purpose which merits another meh. This seems like a big red sign to me:



          if ( ui->random->isChecked () ) 
          _generateNumbers (0, numbersCount, true); // low = 0, high = numbersCount ?



          Does this use case not imply that the generated numbers should be between 0 and numbersCount? Apparently not... Apparently, low and high in that context means to generate high – low number of values.



          Since the purposes and use cases are different, it only makes sense to have different implementations, so branch your if-else well ahead of the for-loop(s).



          void Generator::_generateNumbers( int low, int high, bool random ) 

          QString separator = _getSeparator();

          if (random)
          int numbersCount = ui->numbers->value();
          // generate random numbers between low and high
          // for (int i = 0; i < numbersCount; i++)
          // ...
          else
          // generate random numbers between low and high
          // ...


          // get rid of the last separator char
          if ( _oneLineOutput () && separator != "" ) _removeLastChar(_nums);



          3. UI



          On the UI side, I'd consider removing some borders – they do get in the way, especially the ones around Generate Numbers and the ones around your four buttons.



          You should also consider disabling the How many numbers spinbox if the selected number pattern is Sequential as the two are mutually exclusive options.



          But then, you could also consider the case where the user selects Sequential and provides a from-value and how-many-numbers-value but doesn't provide a to-value. Sounds like you could make this a third Numbers option: Sequential-n.



          It's unfortunate that we don't get the .ui to play around with, but nonetheless, it looks stunning and functional from afar. :-)






          share|improve this answer










          New contributor




          TrebledJ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.






          $endgroup$



          Seems like you've made a lot of improvements since your previous post! Let's get into the review!



          1. General Overview



          a. Use the on_<objectName>_<signal> Naming Scheme for Slots



          This naming scheme tells the moc to automatically connect a slot with the corresponding <signal> of <objectName> from the UI. We then don't need to call connect(...), saving us a few lines of code.



          If we take a look at the clearButton UI object, we can get this auto-connect behaviour by renaming the clear method to on_clearButton_clicked. The implementation doesn't change, only the symbol.



          This process of pinpointing the correct slot name is automated from Design mode. First, right-click the object itself or the listing on the object-class tree. Then select the signal to connect and the slot to go to. Qt will automatically generate the on_clearButton_clicked slot in the header and source files (if it doesn't exist yet).



          Right-click on the Clear button and select Go to slot...
          Right-click on your Clear button to bring up the context menu and select Go to slot...



          enter image description here
          Choose the clicked() signal and click OK.



          Now you no longer need manually connect with connect(...). You can apply this to generateButton, clearButton, saveButton, minimumSpinBox, and maximumSpinBox. Yay, 5 less lines of code! 5 less worries!



          (To be clear, static_cast<void (QSpinBox::*)(int)> isn't needed for minimumSpinBox, and maximumSpinBox as the correct overload can be automatically deduced.)



          Also note that this naming scheme doesn't have to be used for every slot – it is primarily used for those slots which have a corresponding signal from the UI.



          b. Consistency in Order of Methods in Header and Source Files



          In your header file, the first four function-like declarations are



          public:
          explicit Generator(QWidget *parent = nullptr);
          ~Generator();
          public slots:
          void generateNumber();
          void clear();


          However, in your source file, the definition for the destructor comes last. This harms readability. Most readers may be expecting the same ordering of methods in both header and source files. Does this mean the header file should conform to the ordering of the source file? Something like below perhaps?



          public:
          explicit Generator(QWidget *parent = nullptr);
          public slots:
          void generateNumber();
          void clear();
          public:
          ~Generator();


          Nawww, the source file should conform to the header file. Please, please, please; if you declare the destructor right after the constructor, define the destructor right after the constructor.



          Generator::Generator(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::Generator)

          ui->setupUi(this);
          connect(ui->generateButton, &QPushButton::clicked, this, &Generator::generateNumber);
          connect(ui->clearButton, &QPushButton::clicked, this, &Generator::clear);
          connect(ui->saveButton, &QPushButton::clicked, this, &Generator::saveToFile);
          connect(ui->exitButton, &QPushButton::clicked, this, &QApplication::exit);
          connect(ui->minimumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMinValue);
          connect(ui->maximumSpinBox, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &Generator::setMaxValue);


          Generator::~Generator()
          delete ui;


          // other methods
          // ...


          c. Naming



          i. _generateNumbers(int ?, int ?, bool random)



          A minor issue. You have



          void _generateNumbers( int from, int to, bool random );


          in your header file but



          void Generator::_generateNumbers( int low, int high, bool random ) {


          in your source code. Choose either from/to or low/high, but not both.



          ii. _correctInputParameters and oneLineOutput



          For methods that return bool (also known as predicates), consider starting the method with is or has.



          bool _hasCorrectInputParameters();
          bool _isOneLineOutput();


          Helps with readability. We don't need any special guesswork to infer that these will return bool.



          2. Logic



          The logic and program flow seems a tad messy, let's try cleaning it up!



          a. clear()



          What should this clear? Only the text-edit? I'd clear _nums as well.



          void Generator::clear() 
          ui->textEdit->clear();
          _nums.clear();



          The last thing we want is to have the clear method clear only the gui and leave the variable sitting. Clear everything it all at once! Doing so allows us to pinpoint bugs easier – we don't have to spend 30 minutes digging through the entire code to find a lone _nums = "" placed wrongly.



          b. generateNumber and _generateNumbers and _generateNumber



          First off, these methods could do with better naming. As soon as I type generate, the IDE completer will show these three methods and it all suddenly becomes ambiguous. Be specific with what each method does.




          • _generateNumber only generates random numbers, so change it to _generateRandomNumber.


          • generateNumber handles the button click, so follow the first section of this answer and change it to on_generateButton_clicked.


          • _generateNumbers is a fine name as it is.

          Down to the logic. It doesn't really make sense to retrieve values of minimumSpinBox and maximumSpinBox in two places (one, in generateNumber, under the else branch; and two, in _generateNumber). Retrieve it once, then pass it accordingly. By the same principle, since only the random option needs int numbersCount = ui->numbers->value();, this should be placed in _generateNumbers instead.



          void Generator::generateNumber() 
          clear();
          // _nums = ""; // moved to clear(); same as _nums.clear()

          int low = ui->minimumSpinBox->value(); // retrieve values from spinboxes ONCE
          int high = ui->maximumSpinBox->value();

          _generateNumbers(low, high+1, ui->random->isChecked()); // universal, no need for if-else

          ui->textEdit->setText(_nums);



          This also means changing _generateNumber to accept parameters so that we can later pass the low and high in generateNumber:



          qint32 Generator::_generateNumber(int low, int high) 
          std::random_device rd;
          std::default_random_engine eng(rd());
          std::uniform_int_distribution<qint32> distr(low, high);
          return distr(eng);



          Currently, _generateNumbers serves two purposes: generating random numbers and generating sequential numbers. However, the arguments used are for completely different purposes, which is... meh... until their names contradict with their purpose which merits another meh. This seems like a big red sign to me:



          if ( ui->random->isChecked () ) 
          _generateNumbers (0, numbersCount, true); // low = 0, high = numbersCount ?



          Does this use case not imply that the generated numbers should be between 0 and numbersCount? Apparently not... Apparently, low and high in that context means to generate high – low number of values.



          Since the purposes and use cases are different, it only makes sense to have different implementations, so branch your if-else well ahead of the for-loop(s).



          void Generator::_generateNumbers( int low, int high, bool random ) 

          QString separator = _getSeparator();

          if (random)
          int numbersCount = ui->numbers->value();
          // generate random numbers between low and high
          // for (int i = 0; i < numbersCount; i++)
          // ...
          else
          // generate random numbers between low and high
          // ...


          // get rid of the last separator char
          if ( _oneLineOutput () && separator != "" ) _removeLastChar(_nums);



          3. UI



          On the UI side, I'd consider removing some borders – they do get in the way, especially the ones around Generate Numbers and the ones around your four buttons.



          You should also consider disabling the How many numbers spinbox if the selected number pattern is Sequential as the two are mutually exclusive options.



          But then, you could also consider the case where the user selects Sequential and provides a from-value and how-many-numbers-value but doesn't provide a to-value. Sounds like you could make this a third Numbers option: Sequential-n.



          It's unfortunate that we don't get the .ui to play around with, but nonetheless, it looks stunning and functional from afar. :-)







          share|improve this answer










          New contributor




          TrebledJ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.









          share|improve this answer



          share|improve this answer








          edited 3 hours ago





















          New contributor




          TrebledJ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.









          answered 4 hours ago









          TrebledJTrebledJ

          1505




          1505




          New contributor




          TrebledJ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.





          New contributor





          TrebledJ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.






          TrebledJ is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.







          • 2




            $begingroup$
            Welcome to Code Review! Nice job, first post or not.
            $endgroup$
            – greybeard
            3 hours ago










          • $begingroup$
            I realised I missed out a bunch of stuff on my first read. Had to read the code a third time to actually see a large proportion of the inherent problems. :P
            $endgroup$
            – TrebledJ
            3 hours ago












          • 2




            $begingroup$
            Welcome to Code Review! Nice job, first post or not.
            $endgroup$
            – greybeard
            3 hours ago










          • $begingroup$
            I realised I missed out a bunch of stuff on my first read. Had to read the code a third time to actually see a large proportion of the inherent problems. :P
            $endgroup$
            – TrebledJ
            3 hours ago







          2




          2




          $begingroup$
          Welcome to Code Review! Nice job, first post or not.
          $endgroup$
          – greybeard
          3 hours ago




          $begingroup$
          Welcome to Code Review! Nice job, first post or not.
          $endgroup$
          – greybeard
          3 hours ago












          $begingroup$
          I realised I missed out a bunch of stuff on my first read. Had to read the code a third time to actually see a large proportion of the inherent problems. :P
          $endgroup$
          – TrebledJ
          3 hours ago




          $begingroup$
          I realised I missed out a bunch of stuff on my first read. Had to read the code a third time to actually see a large proportion of the inherent problems. :P
          $endgroup$
          – TrebledJ
          3 hours ago










          sliziky is a new contributor. Be nice, and check out our Code of Conduct.









          draft saved

          draft discarded


















          sliziky is a new contributor. Be nice, and check out our Code of Conduct.












          sliziky is a new contributor. Be nice, and check out our Code of Conduct.











          sliziky is a new contributor. Be nice, and check out our Code of Conduct.














          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217431%2fqt-number-generator-v2%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Bett Inhaltsverzeichnis Geschichte | Bettformen | Bettgrößen | Andere Bezeichnungen | Bettenmangel | Betten in der bildenden Kunst | Schlafmedizinische Gesichtspunkte | Siehe auch | Literatur | Weblinks | Einzelnachweise | NavigationsmenüBett, Bettstatt, BettstelleCommons: BettBabybetten: Anwendung, Ausstattungsmerkmale und VergleichskriterienWasserbetten. Vorurteile im TestHapfnNursch10.1007/s11818-012-0584-74006250-8AKS4329276-8

          Luksemburg Sisukord Nimi | Asend | Loodus | Riigikord | Haldusjaotus | Rahvastik | Riigikaitse | Majandus | Taristu | Ajalugu | Eesti ja Luksemburgi suhted | Haridus | Kultuur | Vaata ka | Viited | Välislingid | Navigeerimismenüü50° N, 6° EÜlevaade Luksemburgi kaitsealadest.Luksemburgi rahvaarv. Statistikaamet.World Bank'i andmebaasÜlevaade Luksemburgi loodusest.Ülevaade Luksemburgi metsadest.Guy Colling. "Red List of the Vascular Plants of Luxembourg." Travaux scientifiques du Musée national d’histoire naturelle Luxembourg. 2005.Luxembourg’s biodiversity at risk.Maailma kahepaiksete andmebaas.Denis Lepage. "Luxembourg." Avibase.Ülevaade temperatuuridest. Luksemburgi meteoroloogiateenistus.Ülevaade Luksemburgist. Euroopa Liidu esinduse koduleht.Système politique. TerritoireÜlevaade Luksemburgi rahvastikust. Luksemburgi statistikaamet.Luksemburgi rahvastik. Luksemburgi statistikaamet.The World FactbookMonique Borsenberger, Paul Dickes. "Religions au Luxembourg. Quelle évolution entre 1999-2008". Luksemburgi statistikaamet. 2011.Luksemburgi peapiiskopkond. Catholic-Hierarchy.Luksemburgi armee koduleht.Luksemburgi armee relvastus.Eesti Välisministeerium.Luksemburgi rahvastik. Luksemburgi statistikaamet.Luksemburgi Eesti Seltsi koduleht.Helen Eelrand. "Raadio, mis muutis maailma." Eesti Päevaleht. 13. märts 2004.Ülevaade Luksemburgi haridussüsteemist.Ülevaade Luksemburgi keskkoolidest.Luksemburgr

          Valle di Casies Indice Geografia fisica | Origini del nome | Storia | Società | Amministrazione | Sport | Note | Bibliografia | Voci correlate | Altri progetti | Collegamenti esterni | Menu di navigazione46°46′N 12°11′E / 46.766667°N 12.183333°E46.766667; 12.183333 (Valle di Casies)46°46′N 12°11′E / 46.766667°N 12.183333°E46.766667; 12.183333 (Valle di Casies)Sito istituzionaleAstat Censimento della popolazione 2011 - Determinazione della consistenza dei tre gruppi linguistici della Provincia Autonoma di Bolzano-Alto Adige - giugno 2012Numeri e fattiValle di CasiesDato IstatTabella dei gradi/giorno dei Comuni italiani raggruppati per Regione e Provincia26 agosto 1993, n. 412Heraldry of the World: GsiesStatistiche I.StatValCasies.comWikimedia CommonsWikimedia CommonsValle di CasiesSito ufficialeValle di CasiesMM14870458910042978-6