QMainWindow, no title, border
Solved
General and Desktop
-
I have a QMainWindow which is being used to display status during a process, the Window has no title which is intended, it is also borderless, when the window is visible there is no border or distinction between the window background and windows behind it, I haven't see any flags to make the window borderless, how do I implement a border on a window that has no title?
import.ui
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>ImportRDF</class> <widget class="QMainWindow" name="ImportRDF"> <property name="windowModality"> <enum>Qt::ApplicationModal</enum> </property> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>597</width> <height>108</height> </rect> </property> <property name="minimumSize"> <size> <width>597</width> <height>108</height> </size> </property> <widget class="QWidget" name="centralWidget"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> <widget class="QLabel" name="plblRDFile"> <property name="text"> <string>RDF file:</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> <item row="0" column="1" colspan="3"> <widget class="QLabel" name="plblFilename"> <property name="text"> <string>Device, path and filename</string> </property> </widget> </item> <item row="1" column="0"> <widget class="QLabel" name="plblFilesizeTxt"> <property name="text"> <string>File size:</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> <item row="1" column="1"> <widget class="QLabel" name="plblFilesize"> <property name="contextMenuPolicy"> <enum>Qt::NoContextMenu</enum> </property> <property name="text"> <string>##########</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> <item row="1" column="2"> <widget class="QLabel" name="plblBlocksTxt"> <property name="text"> <string>Blocks:</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> <item row="1" column="3"> <widget class="QWidget" name="gridWidget" native="true"> <property name="contextMenuPolicy"> <enum>Qt::NoContextMenu</enum> </property> <property name="styleSheet"> <string notr="true">margin:0;padding:0;</string> </property> <layout class="QHBoxLayout" name="horizontalLayout"> <property name="spacing"> <number>0</number> </property> <property name="leftMargin"> <number>0</number> </property> <property name="topMargin"> <number>0</number> </property> <property name="rightMargin"> <number>0</number> </property> <property name="bottomMargin"> <number>0</number> </property> <item> <widget class="QLabel" name="plblBlock"> <property name="text"> <string>#######</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> <item> <widget class="QLabel" name="plblOfTxt"> <property name="text"> <string> of </string> </property> </widget> </item> <item> <widget class="QLabel" name="plblTotalBlocks"> <property name="text"> <string>#######</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> <item> <spacer name="horizontalSpacer_2"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item> <widget class="QLabel" name="plblChunksizeTxt"> <property name="text"> <string>Chunk size:</string> </property> <property name="alignment"> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> </property> </widget> </item> <item> <widget class="QLabel" name="plblRead"> <property name="text"> <string>########</string> </property> </widget> </item> <item> <spacer name="horizontalSpacer_3"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item> <widget class="QLabel" name="plblBScansTxt"> <property name="text"> <string>BScans:</string> </property> </widget> </item> <item> <widget class="QLabel" name="plblBScans"> <property name="text"> <string>#####</string> </property> </widget> </item> <item> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item> <widget class="QLabel" name="plblElapsedTxt"> <property name="text"> <string>Elapsed:</string> </property> </widget> </item> <item> <widget class="QLabel" name="plblElapsed"> <property name="text"> <string>##:##:##.###</string> </property> </widget> </item> </layout> </widget> </item> <item row="2" column="0" colspan="4"> <widget class="QProgressBar" name="pgbrStatus"> <property name="value"> <number>24</number> </property> </widget> </item> <item row="3" column="3"> <widget class="QPushButton" name="pbtnAbort"> <property name="minimumSize"> <size> <width>80</width> <height>24</height> </size> </property> <property name="text"> <string>&Abort</string> </property> </widget> </item> </layout> </widget> </widget> <resources/> <connections/> </ui>
import.h
/** * File: * importrdf.h * * Notes: * This file contains the prototype for the ImportRDF class. * * Static Constants: * mscuint16BlockSize Size of database blob / block size * mscuint16UploadInterval Upload block interval in milliseconds * * Static Members: * mspInstance Pointer to instance of dialog * * Static Methods: * pInstance Access method to mspInstance * * Methods: * ImportRDF Class constructor * ~ImportRDF Class destructor * closeDialog Close the import progress dialog * lngBScans Access method to get BScans in RDF * setDatasetId Access method to set muintDatasetID * startImport Starts file import process * updateElapsedTime Updates the elapsed time display * * Members: * mcnAbortClicked Connection to abort button clicked signal * mdsIn Instance of QDataStream for reading RDF * metTaken Elapsed time taken * mfileRDF Instance of QFile for reading RDF * mpRDF Pointer to RDF helper * mpcBuffer Pointer to buffer to read data block into * mptmrUpload Pointer to timer to upload data block * mpui Pointer to user interface * muint64Block Current block to upload * muint64Total Total number of blocks to upload * muintDatasetID Dataset ID of import * * Signals: * importComplete Emitted when RDF import completed * * Slots: * dbError Slot connected to Trainer::dbError signal ******************************************************************************* * History * 17/05/2021 Written by Simon Platten */ #ifndef IMPORTRDF_H #define IMPORTRDF_H #include <QDataStream> #include <QElapsedTimer> #include <QFile> #include <QLabel> #include <QMainWindow> #include <QProgressBar> #include <QSqlError> #include <QSqlQuery> #include <QSqlResult> #include <QTimer> #include "rdf.h" namespace Ui { class ImportRDF; } class ImportRDF : public QMainWindow { Q_OBJECT private: static const quint16 mscuint16BlockSize; static const quint16 mscuint16UploadInterval; static ImportRDF* mspInstance; QMetaObject::Connection mcnAbortClicked; QDataStream mdsIn; QElapsedTimer metTaken; QFile mfileRDF; RDF* mpRDF; char* mpcBuffer; QTimer* mptmrUpload; Ui::ImportRDF* mpui; quint64 muint64Block, muint64Total; uint muintDatasetID; public: explicit ImportRDF(QWidget* pParent = nullptr); ~ImportRDF(); //Delete copy/move so additional instances can't be created/moved ImportRDF(const ImportRDF&) = delete; ImportRDF& operator=(const ImportRDF&) = delete; ImportRDF(ImportRDF&&) = delete; ImportRDF& operator=(ImportRDF&&) = delete; void closeDialog(); static ImportRDF* pInstance() { return ImportRDF::mspInstance; } bool startImport(const QString& crstrFilename, const quint64 cuint64Size); long lngBScans(); void setDatasetId(uint uintDatasetID) { muintDatasetID = uintDatasetID; } void updateElapsedTime(); signals: void importComplete(); public slots: void dbError(const QSqlError& crErr); }; #endif // IMPORTRDF_H
import.cpp
/** * File: * importrdf.cpp * * Notes: * This file contains the implementation of the ImportRDF class. * * History: * 17/05/2021 Written by Simon Platten */ #include "importrdf.h" #include "ui_importRDF.h" #include "trainer.h" //Static initialisation //UDP can send up to 65536 (64K) in a single packet, however we //need to allow for the format of how the data is being sent. //It will be repackaged as a hex string which means two hex nibbles //1 hex character for each nibble which means allowing for the //packet overhead and nibble conversion that it will be considerable //less. //65536 - 256 (message overhead) = Available chunk payload //Binary data is sent as ASCII nibbles so divide by 2 const quint16 ImportRDF::mscuint16BlockSize = (((65536 - 256) / 2)); const quint16 ImportRDF::mscuint16UploadInterval = 10; ImportRDF* ImportRDF::mspInstance = nullptr; /** * @brief ImportRDF::ImportRDF * @param pParent Pointer to parent */ ImportRDF::ImportRDF(QWidget* pParent) : QMainWindow(pParent), mdsIn(&mfileRDF), mpRDF(nullptr), mpui(new Ui::ImportRDF), mptmrUpload(nullptr), mpcBuffer(nullptr), muint64Block(0), muint64Total(0) { ImportRDF::mspInstance = this; mdsIn.setVersion(QDataStream::Qt_DefaultCompiledVersion); setWindowFlags(Qt::FramelessWindowHint); mpui->setupUi(this); mcnAbortClicked = QObject::connect(mpui->pbtnAbort, &QPushButton::clicked, [this]() { //Clean up database removing any incomplete imports QSqlQuery queryCleanup; queryCleanup.prepare("CALL deleteIncompleteDatasets();"); Trainer::queryDB(queryCleanup); emit importComplete(); //Close import dialog closeDialog(); } ); //Allocate enough memory for a single block mpcBuffer = new char[ImportRDF::mscuint16BlockSize]; } /** * @brief ImportRDF::~ImportRDF */ ImportRDF::~ImportRDF() { closeDialog(); QObject::disconnect(mcnAbortClicked); if ( mpRDF != nullptr ) { mpRDF->deleteLater(); } delete mpcBuffer; } /** * @brief ImportRDF::closeDialog */ void ImportRDF::closeDialog() { if ( mfileRDF.isOpen() == true ) { mfileRDF.close(); } //If a timer was created make sure it is stopped and deleted if ( mptmrUpload != nullptr ) { mptmrUpload->stop(); mptmrUpload->deleteLater(); mptmrUpload = nullptr; } close(); } /** * @brief ImportRDF::dbError * @param crErr Constant reference to error */ void ImportRDF::dbError(const QSqlError& crErr) { closeDialog(); Q_UNUSED(crErr); } /** * @brief ImportRDF::lngBScans * @return Number of BScans in RDF or 0 if not ready */ long ImportRDF::lngBScans() { if ( mpRDF != nullptr ) { return mpRDF->lngBScans(); } return 0; } /** * @brief ImportRDF::startImport * @param crstrFilename Constant reference to file name and path * @param cint64Size Constant size of file to import * @return true if file is valid and import can go ahead else false */ bool ImportRDF::startImport(const QString& crstrFilename, const quint64 cuint64Size) { static QString sstrAbort(ImportRDF::tr("&Abort")); static QString sstrImportComplete(ImportRDF::tr("&Import complete")); if ( isVisible() == true || mptmrUpload != nullptr ) { //Import dialog already visible or upload timer already exits, do nothing! return true; } quint64 uint64BlockSize(static_cast<quint64>(ImportRDF::mscuint16BlockSize)); muint64Total = cuint64Size / uint64BlockSize; if ( fmod(cuint64Size, uint64BlockSize) != 0 ) { muint64Total++; } if ( muint64Total == 0 ) { //Nothing to do, abort! return false; } //Populate controls QString strFilename(SckServer::removePath(crstrFilename)); mpui->plblFilename->setText(strFilename); mpui->plblFilesize->setText(QString::number(cuint64Size)); mpui->plblBScans->setText(QString::number(0)); mpui->plblBlock->setText(QString::number(muint64Block)); mpui->plblTotalBlocks->setText(QString::number(muint64Total)); mpui->plblElapsed->setText(SckServer::mscszEmpty); mpui->plblRead->setText("0"); mpui->pgbrStatus->setMinimum(0); mpui->pgbrStatus->setMaximum(muint64Total); //Reset block count muint64Block = 0; mpui->pgbrStatus->setValue(muint64Block); //Hide controls that aren't require yet mpui->plblChunksizeTxt->hide(); mpui->plblRead->hide(); mpui->pgbrStatus->hide(); //Ensure the button text is set-back to "Abort" mpui->pbtnAbort->setText(sstrAbort); //Start the elapsed time taken metTaken.start(); //Show the form show(); if ( mpRDF == nullptr ) { //Add entry to audit log QString strAudit(QString("Reading: %1 to determine BScans").arg(strFilename)); QSqlQuery queryAuditEntry; queryAuditEntry.prepare("CALL addAuditEntry(?);"); queryAuditEntry.addBindValue(strAudit); Trainer::queryDB(queryAuditEntry); //Create instance of RDF helper mpRDF = new RDF(crstrFilename.toLatin1().data()); } if ( mpRDF == nullptr ) { //Shouldn't get here! return false; } QObject::connect(mpRDF, &RDF::BScansUpdate, [this](const long clngBScans) { mpui->plblBScans->setText(QString::number(clngBScans)); updateElapsedTime(); } ); QObject::connect(mpRDF, &RDF::complete, [this, crstrFilename, cuint64Size](const long clngBScans) { //Is the file ok? QString strLastError; if ( mpRDF->eLastError(&strLastError) != RDF_file_ok ) { QString strError(QString("Error: '%1' with RDF file: %2") .arg(strLastError).arg(crstrFilename)); Trainer::logError(strError.toLatin1().data()); return; } //Open the file for processing mfileRDF.setFileName(crstrFilename); if ( mfileRDF.open(QFile::ReadOnly) != true ) { QString strError(QString("Cannot open file: %1").arg(crstrFilename)); Trainer::logError(strError.toLatin1().data()); return; } QString strFilename(SckServer::removePath(crstrFilename)); mpui->plblBScans->setText(QString::number(clngBScans)); //Add entry to audit log QString strAudit(QString("Import started of: %1").arg(strFilename)); QSqlQuery queryAuditEntry; queryAuditEntry.prepare("CALL addAuditEntry(?);"); queryAuditEntry.addBindValue(strAudit); Trainer::queryDB(queryAuditEntry); //Create timer to perform upload mptmrUpload = new QTimer(this); QObject::connect(mptmrUpload, &QTimer::timeout, [this, crstrFilename, strFilename, cuint64Size]() { if ( muint64Block < muint64Total ) { //Read a block of data int intRead = mdsIn.readRawData(mpcBuffer, ImportRDF::mscuint16BlockSize); if ( !(intRead > 0) ) { return; } mpui->plblRead->setText(QString::number(intRead)); //Transfer the buffer to the JSON array QByteArray bytaryChunk; for( int i=0; i<intRead; i++ ) { bytaryChunk.append(mpcBuffer[i]); } quint8 uint8Checksum = SckServer::uint8CalcChecksum(mpcBuffer, intRead); //Write block to database QSqlQuery queryBlock; queryBlock.prepare("SELECT addBlock(?,?,?,?,?);"); queryBlock.addBindValue(muintDatasetID); queryBlock.addBindValue(strFilename); queryBlock.addBindValue(muint64Block); queryBlock.addBindValue(bytaryChunk, QSql::Binary); queryBlock.addBindValue(uint8Checksum); if ( Trainer::queryDB(queryBlock) == true ) { //Increment block counter and update progress bar mpui->pgbrStatus->setValue(++muint64Block); mpui->plblBlock->setText(QString::number(muint64Block)); //Show elapsed time updateElapsedTime(); } } else { //Update the number of chunks/blocks in the dataset RDF file bool blnComplete(muint64Block == muint64Total); QSqlQuery queryChunks; queryChunks.prepare("CALL updateChunks(?,?,?,?);"); queryChunks.addBindValue(crstrFilename); queryChunks.addBindValue(muint64Block); queryChunks.addBindValue(cuint64Size); queryChunks.addBindValue(((blnComplete == true) ? 1 : 0)); Trainer::queryDB(queryChunks); //Add entry to audit log QString strAudit(QString("%1 of: %2").arg(sstrImportComplete) .arg(strFilename)); QSqlQuery queryAudit; queryAudit.prepare("CALL addAuditEntry(?);"); queryAudit.addBindValue(strAudit); Trainer::queryDB(queryAudit); //Change the abort button text mpui->pbtnAbort->setText(sstrImportComplete); //Stop timer mptmrUpload->stop(); } } ); mptmrUpload->start(ImportRDF::mscuint16UploadInterval); //Add stage audit entry queryAuditEntry.prepare("CALL addAuditEntry(?);"); queryAuditEntry.addBindValue(QString("%1: %2 %3 %4") .arg(tr("BScans")) .arg(mpui->plblBScans->text()) .arg(tr("Time taken")) .arg(mpui->plblElapsed->text())); Trainer::queryDB(queryAuditEntry); //Make sure the progress bar is visible mpui->plblChunksizeTxt->show(); mpui->plblRead->show(); mpui->pgbrStatus->show(); } ); return true; } /** * @brief ImportRDF::updateElapsedTime */ void ImportRDF::updateElapsedTime() { static const quint64 scuint64MSinSec = 1 * 1000; static const quint64 scuint64MSinMin = scuint64MSinSec * 60; static const quint64 scuint64MSinHr = scuint64MSinMin * 60; qint64 int64Hours, int64Mins, int64Secs; qint64 int64MS(metTaken.elapsed()); int64Hours = int64MS / scuint64MSinHr; int64MS -= int64Hours * scuint64MSinHr; int64Mins = int64MS / scuint64MSinMin; int64MS -= int64Mins * scuint64MSinMin; int64Secs = int64MS / scuint64MSinSec; int64MS -= int64Secs * scuint64MSinSec; QString strHHMMSSZZZ = QString("%1:%2:%3.%4") .arg(int64Hours, 2, 10, QLatin1Char('0')) .arg(int64Mins, 2, 10, QLatin1Char('0')) .arg(int64Secs, 2, 10, QLatin1Char('0')) .arg(int64MS, 3, 10, QLatin1Char('0')); mpui->plblElapsed->setText(strHHMMSSZZZ); }
-
@SPlatten said in QMainWindow, no title, border:
how do I implement a border on a window that has no title?
Can't you simply add a QFrame to your window?