/* user graph settings Implementation * * Copyright (c) 2022-2024 The OSCAR Team * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of the source code * for more details. */ #define TEST_MACROS_ENABLEDoff #include #include #include #include #include #include #include #include #include #include #include #include "SleepLib/profiles.h" #include "saveGraphLayoutSettings.h" #define USE_FRAMELESS_WINDOW_off #define USE_PROFILE_SPECIFIC_FOLDERoff // off implies saved layouts worked for all profiles. SaveGraphLayoutSettings::SaveGraphLayoutSettings(QString title,QWidget* parent) : parent(parent),title(title) { createSaveFolder(); if (dir==nullptr) return; dir->setFilter(QDir::Files | QDir::Readable | QDir::Writable | QDir::NoSymLinks); QString descFileName = dirName+title.toLower()+".descriptions.txt"; descriptionMap = new DescriptionMap (dir,descFileName); createMenu() ; menu.dialog->connect(menuAddFullBtn, SIGNAL(clicked()), this, SLOT (addFull_feature() )); menu.dialog->connect(menuAddBtn, SIGNAL(clicked()), this, SLOT (add_feature() )); menu.dialog->connect(menuRestoreBtn, SIGNAL(clicked()), this, SLOT (restore_feature() )); menu.dialog->connect(menuUpdateBtn, SIGNAL(clicked()), this, SLOT (update_feature() )); menu.dialog->connect(menuRenameBtn, SIGNAL(clicked()), this, SLOT (rename_feature() )); menu.dialog->connect(menuDeleteBtn, SIGNAL(clicked()), this, SLOT (delete_feature() )); menu.dialog->connect(menuHelpBtn, SIGNAL(clicked()), this, SLOT (help_feature() )); menu.dialog->connect(menuList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*) )); menu.dialog->connect(menuList, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged() )); singleLineRe = new QRegularExpression( QString("^\\s*([^\\r\\n]{0,%1})").arg(1+maxDescriptionLen) ); fileNumRe = new QRegularExpression( QString("%1(\\d+)(.shg)?$").arg(fileBaseName) ); parseFilenameRe = new QRegularExpression(QString("^(%1[.](%2(\\d*)))[.]shg$").arg(title).arg(fileBaseName)); } SaveGraphLayoutSettings::~SaveGraphLayoutSettings() { if (dir==nullptr) {return;} menu.dialog->disconnect(menuAddFullBtn, SIGNAL(clicked()), this, SLOT (addFull_feature() )); menu.dialog->disconnect(menuAddBtn, SIGNAL(clicked()), this, SLOT (add_feature() )); menu.dialog->disconnect(menuRestoreBtn, SIGNAL(clicked()), this, SLOT (restore_feature() )); menu.dialog->disconnect(menuUpdateBtn, SIGNAL(clicked()), this, SLOT (update_feature() )); menu.dialog->disconnect(menuRenameBtn, SIGNAL(clicked()), this, SLOT (rename_feature() )); menu.dialog->disconnect(menuDeleteBtn, SIGNAL(clicked()), this, SLOT (delete_feature() )); menu.dialog->disconnect(menuHelpBtn, SIGNAL(clicked()), this, SLOT (help_feature() )); menu.dialog->disconnect(menuList, SIGNAL(itemChanged(QListWidgetItem*)), this, SLOT(itemChanged(QListWidgetItem*) )); menu.dialog->disconnect(menuList, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged() )); helpDestructor(); delete descriptionMap; delete singleLineRe; delete fileNumRe; delete parseFilenameRe; } void SaveGraphLayoutSettings::createSaveFolder() { // Insure that the save folder exists // Get the directory name for the save files //QString layoutFileFolder = "savedGraphLayoutSettings/"; QString layoutFileFolder = "layoutSettings/"; #if 0 // home directory for the current profile. QString baseName = p_profile->Get("{DataFolder}/"); #else // home directory for all profiles. // allows settings to be shared accross profiles. QString baseName = p_pref->Get("{home}/"); #endif dirName = baseName+layoutFileFolder; // Check if the save folder exists QDir* tmpDir = new QDir(dirName); if (!tmpDir->exists()) { QDir* baseDir=new QDir(baseName); if (!baseDir->exists()) { // Base folder does not exist - terminate return ; } // saved Setting folder does not exist. make it if (!baseDir->mkdir(dirName)) { // Did not create the folder. return ; } tmpDir = new QDir(dirName); // double check if save folder exists or not. if (!tmpDir->exists()) { return ; } } dir=tmpDir; } QPushButton* SaveGraphLayoutSettings::menuBtn(QString name, QIcon* icon, QString style,QSizePolicy::Policy hPolicy,QString tooltip) { return newBtnRtn(menuLayoutButtons, name, icon, style, hPolicy,tooltip) ; } //QPushButton* SaveGraphLayoutSettings::helpBtn(QString name, QIcon* icon, QString style,QSizePolicy::Policy hPolicy,QString tooltip) { //return newBtnRtn(menuLayoutButtons, name, icon, style, hPolicy,tooltip) ; //} QPushButton* SaveGraphLayoutSettings::newBtnRtn(QHBoxLayout* layout,QString name, QIcon* icon, QString style,QSizePolicy::Policy hPolicy,QString tooltip) { QPushButton* button = new QPushButton(name, menu.dialog); button->setIcon(*icon); button->setStyleSheet(style); button->setSizePolicy(hPolicy,QSizePolicy::Fixed); button->setToolTip(tooltip); button->setToolTipDuration(AppSetting->tooltipTimeout()); button->setFont(*mediumfont); layout->addWidget(button); return button; } void SaveGraphLayoutSettings::createStyleSheets() { styleOn= calculateButtonStyle(true,false); styleOff= calculateButtonStyle(false,false); styleExit= calculateButtonStyle(true,true); styleMessageBox= "QMessageBox { " "background-color:yellow;" //"color:black;" "color:red;" "border: 2px solid black;" "text-align: right;" "font-size: 16px;" "}" "QTextEdit {" "background-color:lightblue;" //"color:black;" "color:red;" "border: 9px solid black;" "text-align: center;" "vertical-align:top;" "}" ; styleDialog= QString ( R"( QDialog { border: 3px solid black; } )") ; } void SaveGraphLayoutSettings::createMenu() { if(menu.dialog) return; initDialog(menu,tr("Manage Save Layout Settings") ); createStyleSheets(); QString styleDialog( R"( QDialog { border: 3px solid black; } )") ; menu.dialog->setStyleSheet(styleDialog); menuLayoutButtons = new QHBoxLayout(); menuAddFullBtn = menuBtn(tr("Add" ),m_icon_add , styleOff ,QSizePolicy::Minimum, tr("Add Feature inhibited. The maximum number of Items has been exceeded.") ); menuAddBtn = menuBtn(tr("Add" ),m_icon_add , styleOn ,QSizePolicy::Minimum, tr("creates new copy of current settings.")); menuRestoreBtn = menuBtn(tr("Restore"),m_icon_restore , styleOn ,QSizePolicy::Minimum, tr("Restores saved settings from selection.")); menuRenameBtn = menuBtn(tr("Rename" ),m_icon_rename , styleOn ,QSizePolicy::Minimum, tr("Renames the selection. Must edit existing name then press enter.")); menuUpdateBtn = menuBtn(tr("Update" ),m_icon_update , styleOn ,QSizePolicy::Minimum, tr("Updates the selection with current settings.")); menuDeleteBtn = menuBtn(tr("Delete" ),m_icon_delete , styleOn ,QSizePolicy::Minimum, tr("Deletes the selection.")); menuHelpBtn = menuBtn("" ,m_icon_help , styleOn ,QSizePolicy::Fixed , tr("Expanded Help menu.")); menuList = new QListWidget(menu.dialog); menuList->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); menuList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); menuList->setFont(menu.font); menu.layout->addLayout(menuLayoutButtons); menu.layout->addWidget(menuList, 1); //menuList->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred); menuList->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); }; void HelpData::setDialog(QWidget* parent,QString windowsTitle) { if (dialog) return; open=false; #ifdef USE_FRAMELESS_WINDOW dialog= new QDialog(parent, Qt::FramelessWindowHint); title.setText(QString("

%1

").arg(windowsTitle) ); headerLayout = new QHBoxLayout(); #else dialog = new QDialog(nullptr, Qt::WindowTitleHint | Qt::WindowCloseButtonHint|Qt::WindowSystemMenuHint); dialog->setWindowTitle(windowsTitle) ; dialog->setWindowModality(Qt::WindowModal); dialog->setStyleSheet(QString ( "QDialog { border: 3px solid black; }")); #endif Q_UNUSED(parent); font = QApplication::font(); fontBold = font; fontBold.setWeight(QFont::Bold); layout = new QVBoxLayout(dialog); } void SaveGraphLayoutSettings::initDialog( HelpData & aHelp , QString title ) { if(aHelp.dialog) return; aHelp.setDialog(parent,title); #ifdef USE_FRAMELESS_WINDOW aHelp.headerLayout->addWidget(&aHelp.title); aHelp.exitBtn = newBtnRtn(aHelp.headerLayout, "", m_icon_exit, styleExit , QSizePolicy::Fixed, tr("Exits the dialog menu.")) ; aHelp.layout->addLayout(aHelp.headerLayout); #endif // YXXXXXXXXXXXXXXXXXXX // dialog->setFont(font) ; aHelp.dialog->setSizeGripEnabled(true); // allows lower right hand corner to resize dialog aHelp.dialog->setStyleSheet(QString ( "QDialog { border: 3px solid black; }")); } void SaveGraphLayoutSettings::createHelp() { createHelp(help, tr("Help Menu - Manage Layout Settings"), helpInfo()); if (help.exitBtn) help.dialog->connect(help.exitBtn, SIGNAL(clicked()), this, SLOT (help_exit_feature() )); }; void SaveGraphLayoutSettings::createHelp(HelpData & ahelp , QString title , QString text) { if(ahelp.dialog) return; initDialog(ahelp,title ); ahelp.label = new QLabel(parent); ahelp.label->setFont(ahelp.font); ahelp.label->setText(text) ; ahelp.layout->addWidget(ahelp.label, 1); } void SaveGraphLayoutSettings::helpDestructor() { closeHelp(); closeHint(); closeMenu(); if (hint.exitBtn) hint.dialog->disconnect(hint.exitBtn, SIGNAL(clicked()), this, SLOT ( closeHint() )); if (help.exitBtn) help.dialog->disconnect(help.exitBtn, SIGNAL(clicked()), this, SLOT ( closeHelp() )); if (menu.exitBtn) menu.dialog->disconnect(menu.exitBtn, SIGNAL(clicked()), this, SLOT ( help_exit_feature() )); } #define TABLES QString(R"( )") #define TABLEE QString(R"(
)") #define CENTERS QString(R"(

)") #define CENTERE QString(R"(

)") #define BREAK QString(R"(
)") #define PARAS QString(R"(

)") #define PARAE QString(R"(

)") #define ROWS QString(R"( )") #define ROWE QString(R"( )") #define COLS QString(R"( )") #define COLE QString(R"( )") #define CSEP QString(R"( )") QString SaveGraphLayoutSettings::hintInfo() { QStringList strList; strList << CENTERS << "" << tr("Basic Hints") << "" << CENTERE << TABLES << ROWS << COLS << "" << QString(tr("Key Sequence")) << "" << CSEP << "" << QString(tr("Description")) << "" << COLE << ROWE << ROWS << COLS << QString(tr("MouseWheel")) << CSEP << QString(tr("Scrolls unpinned Graphs")) << COLE << ROWE << ROWS << COLS << QString(tr("Ctrl + MouseWheel")) << CSEP << QString(tr("Zooms Time Selection")) << COLE << ROWE << ROWS << COLS << QString(tr("LeftMouse dragDrop")) << CSEP << QString(tr("Defines Time Selection")) << COLE << ROWE << ROWS << COLS << QString(tr("RightMouse dragDrop")) << CSEP << QString(tr("Moves Time Selection")) << COLE << ROWE << ROWS << COLS << QString(tr("Ctrl + (right/left)MouseClick")) << CSEP << QString(tr("Zooms Time Selection")) << COLE << ROWE << ROWS << COLS << QString(tr(" (right/left)MouseClick")) << CSEP << QString(tr("Moves Time Selection")) << COLE << ROWE << BREAK << ROWS << COLS << QString(tr("(right/left) Arrow (Ctrl => faster)")) << CSEP << QString(tr("Moves Time Selection")) << COLE << ROWE << ROWS << COLS << QString(tr("Up/Down Arrow")) << CSEP << QString(tr("Scrolls graphs")) << COLE << ROWE << ROWS << COLS << QString(tr("Up/Down Arrow+Focus")) << CSEP << QString(tr("Zooms graphs")) << COLE << ROWE << TABLEE << CENTERS << "" << tr("Graph Layout Hints") << "" << CENTERE << TABLES << ROWS << COLS << QString(tr("Double Click Graph Title")) << CSEP << QString(tr("Toggles Pinning")) << COLE << ROWE << ROWS << COLS << QString(tr("Daily:Double Click Y-axis label")) << CSEP << QString(tr("Toggle Time Selection Auto Zoom")) << COLE << ROWE << ROWS << COLS << QString(tr("DragDrop Graph Title")) << CSEP << QString(tr("Reorders Graph layout")) << COLE << ROWE << ROWS << COLS << QString(tr("DragDrop graph’s bottom line")) << CSEP << QString(tr("Changes Size of Graphs")) << COLE << ROWE << ROWS << COLS << QString(tr("Layout Button (next to Graph Button)")) << CSEP << QString(tr("Save / Restore Graph Layouts")) << COLE << ROWE << TABLEE << CENTERS << "" << tr("Daily Graph Hints") << "" << CENTERE << TABLES << ROWS << COLS << QString(tr("Click on date")) << CSEP << QString(tr("Toggle Calendar on/off")) << COLE << ROWE << ROWS << COLS << QString(tr("Detailed: Click on colored event")) << CSEP << QString(tr("Jump to event tab with event opened")) << COLE << ROWE << ROWS << COLS << QString(tr("Detailed: Click on a session (at bottom)")) << CSEP << QString(tr("Toggle session disable / enable session")) << COLE << ROWE << ROWS << COLS << QString(tr("Event: Click on an event")) << CSEP << QString(tr("Time Selection 3 min before event 20 sec after")) << COLE << ROWE << ROWS << COLS << QString(tr("Bookmark")) << CSEP << QString(tr("Save current Time Selection")) << COLE << ROWE << ROWS << COLS << QString(tr("Search Tab")) << CSEP << QString(tr("Search data base")) << COLE << ROWE << TABLEE << CENTERS << "" << tr("Miscellaneous Hints") << "" << CENTERE << TABLES << ROWS << COLS << QString(tr("OverView: Shift Click on a date")) << CSEP << QString(tr("Jumps to date in the Daily Tab")) << COLE << ROWE << ROWS << COLS << QString(tr("Daily: Event (bottom left corner) ")) << CSEP << QString(tr("Select Events to view")) << COLE << ROWE << ROWS << COLS << QString(tr("Graph / Chart (bottom right corner)")) << CSEP << QString(tr("Selects graphs to view")) << COLE << ROWE << TABLEE ; return strList.join("\n"); } QString SaveGraphLayoutSettings::helpInfo() { QStringList strList; strList<") <") <") <

") < ") <
") < ") <") <") <") <") <
") < ") <
") < ") <
") <") <
") <") <") <
") < ") <") <
") <
") < ") <
") < ") <
") < ") <

") <

") < ") < ") < ") <
") < ") < ") < ") <

") <

  • ") <
  • ") <
  • ") <") <") <") <
  • ") <
"); return strList.join("\n"); }; const QString SaveGraphLayoutSettings::calculateStyleMessageBox(QFont* font , QString& s1, QString& s2) { QFontMetrics fm = QFontMetrics(*font); int width = fm.boundingRect(s1).size().width(); int width2 = fm.boundingRect(s2).size().width(); width = qMax(width,width2) + iconWidthMessageBox; QString style = QString("%1 QLabel{%2 min-width: %3px;}" ). arg(styleMessageBox). arg("text-align: center;" "color:black;"). arg(width); return style; } bool SaveGraphLayoutSettings::verifyItem(QListWidgetItem* item,QString text,QIcon* icon) { //if (verifyhelp() ) return false; if (item) return true; initminMenuListSize(); confirmAction( text ,"" , icon); return false; } #if 1 bool SaveGraphLayoutSettings::confirmAction(QString top ,QString bottom,QIcon* icon,QMessageBox::StandardButtons flags , QMessageBox::StandardButton adefault, QMessageBox::StandardButton success) { //QString topText=QString("
%1
").arg(top); //QString bottomText=QString("
%1
").arg(bottom); QString topText=QString("

%1

").arg(top); QString bottomText=QString("

%1

").arg(bottom); QMessageBox msgBox(menu.dialog); msgBox.setText(topText); msgBox.setInformativeText(bottomText); if (icon!=nullptr) { msgBox.setIconPixmap(icon->pixmap(QSize(iconWidthMessageBox,iconWidthMessageBox))); } // may be good for help menu. a pull down box with box of data. msgBox.setDetailedText("some detailed string"); msgBox.setStandardButtons(flags); msgBox.setDefaultButton(adefault); msgBox.setWindowFlag(Qt::FramelessWindowHint,true); msgBox.setStyleSheet(calculateStyleMessageBox(&menu.font,top,bottom)); // displaywidgets((QWidget*)&msgBox); bool ret= msgBox.exec()==success; return ret; } #else bool SaveGraphLayoutSettings::confirmAction(QString name ,QString question,QIcon* icon,QMessageBox::StandardButtons flags , QMessageBox::StandardButton adefault, QMessageBox::StandardButton success) { //bool SaveGraphLayoutSettings::confirmAction(QString name,QString question,QIcon* icon) Q_UNUSED(flags); Q_UNUSED(adefault); Q_UNUSED(success); QMessageBox msgBox(menu.dialog); msgBox.setText(question); if (icon!=nullptr) { msgBox.setIconPixmap(icon->pixmap(QSize(50,50))); } msgBox.setStandardButtons(QMessageBox::Cancel | QMessageBox::Yes ); msgBox.setDefaultButton(QMessageBox::Cancel); msgBox.setStyleSheet(styleMessageBox); msgBox.setWindowFlag(Qt::FramelessWindowHint,true); return (msgBox.exec()==QMessageBox::Yes); Q_UNUSED(name); } #endif QString SaveGraphLayoutSettings::calculateButtonStyle(bool on,bool exitBtn){ QString btnStyle=QString("QPushButton{%1%2}").arg(on ?"color: black;background-color:white;" :"color: darkgray;background-color:#e8e8e8 ;" ).arg(!exitBtn ? "" : "background: transparent;" "border-radius: 8px;" "border: 2px solid transparent;" "max-width:1em;" "border:none;" ); QString toolTipStyle=" QToolTip { " "border: 1px solid black;" "border-width: 1px;" "padding: 4px;" "font: 14px ; color:black; background-color:yellow;" "}"; btnStyle.append(toolTipStyle); return btnStyle; } void SaveGraphLayoutSettings::looksOn(QPushButton* button,bool on){ //button->setEnabled(on); button->setStyleSheet(on?styleOn:styleOff); } void SaveGraphLayoutSettings::manageButtonApperance() { bool enable = menuList->currentItem(); looksOn(menuUpdateBtn,enable); looksOn(menuRestoreBtn,enable); looksOn(menuDeleteBtn,enable); looksOn(menuRenameBtn,enable); if (nextNumToUse<0) { // check if at Maximum limit // must always hide first menuAddBtn->hide(); menuAddFullBtn->show(); } else { // must always hide first menuAddFullBtn->hide(); menuAddBtn->show(); } } void SaveGraphLayoutSettings::add_feature() { if(!graphView) return; QString fileName = QString("%1%2").arg(fileBaseName).arg(nextNumToUse,fileNumMaxLength,10,QLatin1Char('0')); writeSettings(fileName); // create a default description - use formatted datetime. QString desc=QDateTime::currentDateTime().toString(); descriptionMap->add(fileName,desc); descriptionMap->save(); QListWidgetItem* item = updateFileList( fileName); if (item!=nullptr) { menuList->setCurrentItem(item,QItemSelectionModel::ClearAndSelect); menuList->editItem(item); } menuList->sortItems(); resizeMenu(); } void SaveGraphLayoutSettings::addFull_feature() { verifyItem( nullptr,tr("Maximum number of Items exceeded.") , m_icon_add); } void SaveGraphLayoutSettings::update_feature() { if(!graphView) return; QListWidgetItem * item=menuList->currentItem(); if (!verifyItem(item, tr("No Item Selected") , m_icon_update)) return ; if(!confirmAction( item->text(), tr("Ok to Update?") , m_icon_update) ) return; QString fileName = item->data(fileNameRole).toString(); writeSettings(fileName); }; void SaveGraphLayoutSettings::restore_feature() { if(!graphView) return; QListWidgetItem * item=menuList->currentItem(); if (!verifyItem(item, tr("No Item Selected") , m_icon_restore)) return ; QString fileName = item->data(fileNameRole).toString(); loadSettings(fileName); closeMenu(); }; void SaveGraphLayoutSettings::rename_feature() { if(!graphView) return; QListWidgetItem * item=menuList->currentItem(); if (!verifyItem(item, tr("No Item Selected") , m_icon_rename)) return ; menuList->editItem(item); // SaveGraphLayoutSettings::itemChanged(QListWidgetItem *item) is called when edit changes the entry. // itemChanged will update the description map } void SaveGraphLayoutSettings::help_exit_feature() { closeMenu(); closeHelp(); } void SaveGraphLayoutSettings::help_feature() { initminMenuListSize(); createHelp(); if(!help.dialog) return; if (help.open) { closeHelp(); return; } help.dialog->raise(); help.open=true; help.dialog->exec(); help.open=false; manageButtonApperance(); } void SaveGraphLayoutSettings::delete_feature() { if(!graphView) return; QListWidgetItem * item=menuList->currentItem(); if (!verifyItem(item, tr("No Item Selected") , m_icon_delete)) return ; if(!confirmAction(item->text(), tr("Ok To Delete?") ,m_icon_delete) ) return; QString fileName = item->data(fileNameRole).toString(); descriptionMap->remove(fileName); descriptionMap->save(); deleteSettings(fileName); delete item; if (nextNumToUse<0) { nextNumToUse=fileNum(fileName); } manageButtonApperance(); resizeMenu(); } void SaveGraphLayoutSettings::itemChanged(QListWidgetItem *item) { QString fileName=item->data(fileNameRole).toString(); QString desc= item->text(); // use only the first line in a multiline string. Can be set using cut and paste QRegularExpressionMatch match = singleLineRe->match(desc); if (match.hasMatch()) { // captured match is the first line and has been truncated desc=match.captured(1).trimmed(); // reoves spaces at end. } else { // no match. // an invalid name was entered. too much white space or empty desc=""; } if (desc.length()>maxDescriptionLen) { desc.append("..."); } if (desc.length() <=0) { // returns name back to previous saved name desc=descriptionMap->get(fileName); } else { descriptionMap->add(fileName,desc); descriptionMap->save(); } item->setText(desc); menuList->sortItems(); menuList->setCurrentItem(item); resizeMenu(); } void SaveGraphLayoutSettings::itemSelectionChanged() { initminMenuListSize(); manageButtonApperance(); } void SaveGraphLayoutSettings::initminMenuListSize() { if (minMenuDialogSize.width()==0) { menuDialogSize = menu.dialog->size(); minMenuDialogSize = menuDialogSize; menuListSize = menuList->size(); minMenuListSize = menuListSize; dialogListDiff = menuDialogSize - menuListSize; dialogListDiff.setWidth (horizontalWidthAdjustment + dialogListDiff.width()); resizeMenu(); } }; void SaveGraphLayoutSettings::writeSettings(QString filename) { graphView->SaveSettings(title+"."+filename,dirName); }; void SaveGraphLayoutSettings::loadSettings(QString filename) { graphView->LoadSettings(title+"."+filename,dirName); }; void SaveGraphLayoutSettings::deleteSettings(QString filename) { QString fileName=graphView->settingsFilename (title+"."+filename,dirName) ; dir->remove(fileName); }; int SaveGraphLayoutSettings::fileNum(QString fileName) { QRegularExpressionMatch match = fileNumRe->match(fileName); int value=-1; if (match.hasMatch()) { value=match.captured(1).toInt(); } return value; } QSize SaveGraphLayoutSettings::maxSize(const QSize AA , const QSize BB ) { return QSize ( qMax(AA.width(),BB.width()) , qMax(AA.height(),BB.height() ) ); } bool SaveGraphLayoutSettings::sizeEqual(const QSize AA , const QSize BB ) { return (AA.width()==BB.width()) && ( AA.height()==BB.height()) ; } void SaveGraphLayoutSettings::resizeMenu() { if (minMenuDialogSize.width()==0) return; QSize newSize = calculateMenuDialogSize(); newSize.setWidth ( newSize.width()); menuDialogSize = menu.dialog->size(); if ( sizeEqual(newSize , menuDialogSize)) { // no work to do return; }; if ( menuDialogSize.width() < newSize.width() ) { menu.dialog->setMinimumWidth(newSize.width()); menu.dialog->setMaximumWidth(QWIDGETSIZE_MAX); } else if ( menuDialogSize.width() > newSize.width() ) { menu.dialog->setMaximumWidth(newSize.width()); menu.dialog->setMinimumWidth(newSize.width()); } if ( menuDialogSize.height() < newSize.height() ) { menu.dialog->setMinimumHeight(newSize.height()); menu.dialog->setMaximumHeight(QWIDGETSIZE_MAX); } else if ( menuDialogSize.height() > newSize.height() ) { menu.dialog->setMaximumHeight(newSize.height()); menu.dialog->setMinimumHeight(newSize.height()); } menuDialogSize = newSize; } QSize SaveGraphLayoutSettings::calculateMenuDialogSize() { if (menuDialogSize.width()==0) return QSize(0,0); QListWidgetItem* item; widestItem=nullptr; QFontMetrics fm = QFontMetrics(menu.font); // account for scrollbars. QSize returnValue = QSize( 0 , fm.height() ); // add an extra space at the bottom. width didn't work // Account for dialog Size returnValue += dialogListDiff; QSize size; for (int index = 0; index < menuList->count(); ++index) { item = menuList->item(index); if (!item) continue; size = fm.boundingRect(item->text()).size(); if (returnValue.width() < size.width()) { returnValue.setWidth( qMax( returnValue.width(),size.width())); widestItem=item; } returnValue.setHeight( returnValue.height()+size.height()); } returnValue.setWidth( horizontalWidthAdjustment + returnValue.width() ) ; returnValue = maxSize(returnValue, minMenuDialogSize); return returnValue; } QListWidgetItem* SaveGraphLayoutSettings::updateFileList(QString find) { QListWidgetItem* ret=nullptr; manageButtonApperance(); dir->refresh(); QFileInfoList filelist = dir->entryInfoList( QDir::Files | QDir::Readable | QDir::Writable | QDir::NoSymLinks,QDir::Name); // Restrict number of files. easy to find availble unused entry for add function. int row=0; int count=0; menuList->clear(); nextNumToUse=-1; descriptionMap->load(); for (int i = 0; i < filelist.size(); ++i) { QFileInfo fileInfo = filelist.at(i); QString fileName = fileInfo.fileName(); QRegularExpressionMatch match = parseFilenameRe->match(fileName); if (match.hasMatch()) { if (match.lastCapturedIndex()==3) { QString fileName=match.captured(2); if (nextNumToUse<0) { // check if an entry is availavle to use int fileNum=match.captured(3).toInt(); // find an available file name(number); if (fileNum!=count) { nextNumToUse=count; } } count++; QListWidgetItem *item = new QListWidgetItem(descriptionMap->get(fileName)); item->setData(fileNameRole,fileName); item->setFlags(item->flags() | Qt::ItemIsEditable); menuList->insertItem(row,item); row++; if (find!=nullptr && fileName==find) { ret=item; } } } } if (nextNumToUse<0) { // check if there is an existing empty slot // if not then the next available slot is at the end. CHeck if at max files. if (countsortItems(); return ret; } void SaveGraphLayoutSettings::closeHelp() { if (help.open) { help.dialog->close(); } } void SaveGraphLayoutSettings::closeHint() { if (hint.open) { hint.dialog->close(); } } void SaveGraphLayoutSettings::closeMenu() { closeHelp(); closeHint(); if (menu.open) { menu.dialog->close(); } } void SaveGraphLayoutSettings::triggerLayout(gGraphView* graphView) { if (dir==nullptr) { //const char* err=qPrintable(QString("Cannot find directory %1").arg(dirName)); //qWarning(err); return; } if (menu.open) { closeMenu(); return; } this->graphView=graphView; updateFileList(); manageButtonApperance(); menu.dialog->raise(); menu.open=true; menu.dialog->exec(); menu.open=false; closeMenu(); } QSize textsize(QFont font ,QString text) { return QFontMetrics(font).size(0 , text); } void SaveGraphLayoutSettings::createHint() { createHelp(hint, tr("Graph Short-Cuts Help"), hintInfo()); if (hint.exitBtn) { hint.dialog->connect(hint.exitBtn, SIGNAL(clicked()), this, SLOT (closeHint())); } }; void SaveGraphLayoutSettings::hintHelp() { if (hint.open) { hint.dialog->close(); return; } createHint(); if (!hint.dialog) return; hint.dialog->raise(); hint.dialog->show(); hint.open=true; hint.dialog->exec(); hint.open=false; } //==================================================================================================== //==================================================================================================== // Descriptions map class with file storage DescriptionMap::DescriptionMap(QDir* dir, QString _filename) { filename = dir->absoluteFilePath(_filename); parseDescriptionsRe = new QRegularExpression(QString("^\\s*(\\w+)%1(.*)$").arg(delimiter) ); }; DescriptionMap::~DescriptionMap() { delete parseDescriptionsRe; }; void DescriptionMap::add(QString key,QString desc) { descriptions.insert(key,desc); }; void DescriptionMap::remove(QString key) { descriptions.remove(key); } QString DescriptionMap::get(QString key) { QString ret =descriptions.value(key,key); return ret; } void DescriptionMap::save() { QFile file(filename); file.open(QFile::WriteOnly); QTextStream out(&file); QMapIteratorit(descriptions); while (it.hasNext()) { it.next(); QString line=QString("%1%2%3\n").arg(it.key()).arg(delimiter).arg(it.value()); out <match(line); if (match.hasMatch()) { QString fileName = match.captured(1); QString desc = match.captured(2); add(fileName,desc); } else { DEBUGF QQ("MATCH ERROR",line); } } } //==================================================================================================== //==================================================================================================== #if 0 Different languages unicodes to test. optained from translation files 도움주신분들 已成功删除 删除 הצג את מחיצת הנתונים הצג את מחיצת הנתונים 已成功删除 عذرا ، لا يمكن تحديد موقع ملف. 已成功删除 عذرا ، لا يمكن تحديد موقع ملف. 删除 Toon gegevensmap عذرا ، لا يمكن تحديد موقع ملف. #endif