inline bool KviModeEditor::modeNeedsParameterOnlyWhenSet(char cMode) { if(!m_pChannel) return false; KviIrcConnectionServerInfo * pServerInfo = m_pChannel->serverInfo(); if(pServerInfo) return pServerInfo->supportedParameterWhenSetModes().contains(cMode); return false; }
inline const QString * KviModeEditor::getModeDescription(char cMode) { if(!m_pChannel) return nullptr; KviIrcConnectionServerInfo * pServerInfo = m_pChannel->serverInfo(); if(pServerInfo) return &(pServerInfo->getChannelModeDescription(cMode)); return nullptr; }
KviModeEditor::KviModeEditor(QWidget * par, KviWindowToolPageButton * button, const char * name, KviChannelWindow * pChan) : KviWindowToolWidget(par, button) { setObjectName(name); m_pChannel = pChan; QGridLayout * pMasterLayout = new QGridLayout(this); setFocusPolicy(Qt::ClickFocus); QScrollArea * pScrollArea = new QScrollArea(this); pScrollArea->viewport()->setBackgroundRole(QPalette::Background); pMasterLayout->addWidget(pScrollArea, 0, 0); pMasterLayout->setRowStretch(1, 1); m_pButton = new QPushButton("", this); pMasterLayout->addWidget(m_pButton, 1, 0); connect(m_pButton, SIGNAL(clicked()), this, SLOT(commit())); if(!m_pChannel || !m_pChannel->connection()) m_pButton->setText(__tr2qs("Close")); QWidget * pBackground = new QWidget(pScrollArea->viewport()); QGridLayout * g = new QGridLayout(pBackground); QLabel * l = new QLabel("", pBackground); l->setPixmap(*(g_pIconManager->getSmallIcon(KviIconManager::Mode))); g->addWidget(l, 0, 0); l = new QLabel(__tr2qs("Channel modes"), pBackground); g->addWidget(l, 0, 1, 1, 1); QFrame * f = new QFrame(pBackground); f->setFrameStyle(QFrame::HLine | QFrame::Sunken); g->addWidget(f, 1, 0, 1, 3); QCheckBox * pCheckBox = nullptr; QLineEdit * pLineEdit = nullptr; int iRow = 1; QString szTmp; QString cDesc; char cMode = 0; //NOTE: this is a fallback is for some reason we don't have a serverInfo() struct available fot this connection // The connection is dead and the context was destroyed, don't guess on what was there if(!m_pChannel || !m_pChannel->connection()) return; // first, the basic checkable modes pstnmi QString szModes = "pstnmi"; while(!szModes.isEmpty()) { cMode = szModes[0].unicode(); szModes.remove(0, 1); szTmp = QString("%1: %2").arg(cMode).arg(*(getModeDescription(cMode))); pCheckBox = new QCheckBox(szTmp, pBackground); m_pCheckBoxes.insert(cMode, pCheckBox); if(pChan) pCheckBox->setChecked(pChan->plainChannelMode().contains(cMode)); iRow++; g->addWidget(pCheckBox, iRow, 0, 1, 3); } // second, che basic modes with parameter lk szModes = "lk"; while(!szModes.isEmpty()) { cMode = szModes[0].unicode(); szModes.remove(0, 1); szTmp = QString("%1: %2").arg(cMode).arg(*(getModeDescription(cMode))); pCheckBox = new QCheckBox(szTmp, pBackground); m_pCheckBoxes.insert(cMode, pCheckBox); iRow++; g->addWidget(pCheckBox, iRow, 0, 1, 3); connect(pCheckBox, SIGNAL(toggled(bool)), this, SLOT(checkBoxToggled(bool))); pLineEdit = new QLineEdit(pBackground); m_pLineEdits.insert(cMode, pLineEdit); iRow++; g->addWidget(pLineEdit, iRow, 1, 1, 2); if(pChan) { if(pChan->hasChannelMode(cMode)) { pCheckBox->setChecked(true); pLineEdit->setText(pChan->channelModeParam(cMode)); } else { pLineEdit->setEnabled(false); } } } // third, check if the we have any info about other modes supported by the server KviIrcConnectionServerInfo * pServerInfo = nullptr; if(m_pChannel) pServerInfo = m_pChannel->serverInfo(); if(!pServerInfo) { g->setRowStretch(++iRow, 1); g->setColumnStretch(2, 1); pScrollArea->setWidget(pBackground); return; } // 4th, more plain modes supported by the server szModes = pServerInfo->supportedPlainModes(); // remove modes that we already implemented szModes.remove("p"); szModes.remove("s"); szModes.remove("t"); szModes.remove("n"); szModes.remove("m"); szModes.remove("i"); while(!szModes.isEmpty()) { cMode = szModes[0].unicode(); szModes.remove(0, 1); cDesc = *(getModeDescription(cMode)); szTmp = QString("%1: %2").arg(cMode).arg(!cDesc.isEmpty() ? cDesc : "Unknown"); pCheckBox = new QCheckBox(szTmp, pBackground); m_pCheckBoxes.insert(cMode, pCheckBox); if(pChan) pCheckBox->setChecked(pChan->plainChannelMode().contains(cMode)); iRow++; g->addWidget(pCheckBox, iRow, 0, 1, 3); } iRow++; // parameterized modes szModes = pServerInfo->supportedParameterModes(); szModes.append(pServerInfo->supportedParameterWhenSetModes()); // remove modes that we already implemented szModes.remove("k"); szModes.remove("l"); while(!szModes.isEmpty()) { cMode = szModes[0].unicode(); szModes.remove(0, 1); cDesc = *(getModeDescription(cMode)); szTmp = QString("%1: %2").arg(cMode).arg(!cDesc.isEmpty() ? cDesc : "Unknown"); pCheckBox = new QCheckBox(szTmp, pBackground); m_pCheckBoxes.insert(cMode, pCheckBox); iRow++; g->addWidget(pCheckBox, iRow, 0, 1, 3); connect(pCheckBox, SIGNAL(toggled(bool)), this, SLOT(checkBoxToggled(bool))); pLineEdit = new QLineEdit(pBackground); m_pLineEdits.insert(cMode, pLineEdit); iRow++; g->addWidget(pLineEdit, iRow, 1, 1, 2); if(pChan->hasChannelMode(cMode)) { pCheckBox->setChecked(true); pLineEdit->setText(pChan->channelModeParam(cMode)); } else { pLineEdit->setEnabled(false); } } g->setRowStretch(++iRow, 1); g->setColumnStretch(2, 1); pScrollArea->setWidget(pBackground); updateOpStatus(); if(m_pChannel) connect(m_pChannel, SIGNAL(opStatusChanged()), this, SLOT(updateOpStatus())); }
void KviModeEditor::commit() { if(!m_pChannel) { emit done(); return; } QMap<char, QString> szPlusModes; QMap<char, QString> szMinusModes; QCheckBox * pCheckBox; QLineEdit * pLineEdit; char cMode = 0; QList<char> modes = m_pCheckBoxes.keys(); for(int i = 0; i < modes.count(); ++i) { cMode = modes.at(i); pCheckBox = m_pCheckBoxes.value(cMode); if(!pCheckBox) continue; // wtf!? pLineEdit = m_pLineEdits.value(cMode); if(pLineEdit) { // mode with parameter (with an exception) if(pCheckBox->isChecked()) { // mode is checked if(!m_pChannel->hasChannelMode(cMode) || (pLineEdit->text().trimmed() != m_pChannel->channelModeParam(cMode))) { // mode was not checked before, or the parameter has changed szPlusModes.insert(cMode, pLineEdit->text().trimmed()); } } else { // mode is not checked if(m_pChannel->hasChannelMode(cMode)) { // but it was checked before // checks if this specific mode does not need a parameter when set if(modeNeedsParameterOnlyWhenSet(cMode)) { szMinusModes.insert(cMode, QString()); } else { szMinusModes.insert(cMode, m_pChannel->channelModeParam(cMode)); } } } } else { //mode without parameter if(pCheckBox->isChecked()) { if(!m_pChannel->plainChannelMode().contains(cMode)) szPlusModes.insert(cMode, QString()); } else { if(m_pChannel->plainChannelMode().contains(cMode)) szMinusModes.insert(cMode, QString()); } } } // now flush out mode changes int iModesPerLine = 3; // a good default KviIrcConnectionServerInfo * pServerInfo = nullptr; if(m_pChannel) pServerInfo = m_pChannel->serverInfo(); if(pServerInfo) { iModesPerLine = pServerInfo->maxModeChanges(); if(iModesPerLine < 1) iModesPerLine = 1; } QString szModes; QStringList szParameters; int iModes = 0; QMap<char, QString>::const_iterator iter = szMinusModes.constBegin(); while(iter != szMinusModes.constEnd()) { if(iter == szMinusModes.constBegin()) szModes.append("-"); szModes.append(iter.key()); szParameters.append(iter.value()); ++iModes; ++iter; //time to commit? if(iModes == iModesPerLine) { QString szCommitModes = szModes; if(iter == szMinusModes.constEnd()) szModes.clear(); else szModes = "-"; if(szParameters.count()) { szCommitModes.append(QChar(' ')); szCommitModes.append(szParameters.join(QString(" "))); szParameters.clear(); } iModes = 0; emit setMode(szCommitModes); } } iter = szPlusModes.constBegin(); while(iter != szPlusModes.constEnd()) { if(iter == szPlusModes.constBegin()) szModes.append("+"); szModes.append(iter.key()); szParameters.append(iter.value()); ++iModes; ++iter; //time to commit? this should be an ==, but includes the minus sign so "+aaa" = 4 chars if(iModes == iModesPerLine) { QString szCommitModes = szModes; if(iter == szPlusModes.constEnd()) szModes.clear(); else szModes = "+"; if(szParameters.count()) { szCommitModes.append(QChar(' ')); szCommitModes.append(szParameters.join(QString(" "))); szParameters.clear(); } iModes = 0; emit setMode(szCommitModes); } } if(iModes) { QString szCommitModes = szModes; szModes.clear(); if(szParameters.count()) { szCommitModes.append(QChar(' ')); szCommitModes.append(szParameters.join(QString(" "))); szParameters.clear(); } emit setMode(szCommitModes); } emit done(); }
KviMaskEditor::KviMaskEditor(QWidget * par, KviChannelWindow * pChannel, KviWindowToolPageButton * button, std::vector<KviMaskEntry *> maskList, char cMode, const char * name) : KviWindowToolWidget(par, button) { setObjectName(name); m_pChannel = pChannel; setFocusPolicy(Qt::ClickFocus); QGridLayout * g = new QGridLayout(this); m_cFlag = cMode; KviIrcConnectionServerInfo * pServerInfo = nullptr; QString szDescription = ""; if(m_pChannel) pServerInfo = m_pChannel->serverInfo(); if(pServerInfo) szDescription = pServerInfo->getChannelModeDescription(cMode); if(szDescription.isEmpty()) szDescription = __tr2qs("Mode \"%1\" masks").arg(cMode); switch(cMode) { case 'b': m_eIcon = KviIconManager::Ban; break; case 'e': m_eIcon = KviIconManager::BanExcept; break; case 'I': m_eIcon = KviIconManager::InviteExcept; break; case 'a': m_eIcon = KviIconManager::ChanAdmin; break; case 'q': // this could also be quiet bans.. m_eIcon = KviIconManager::Kick; break; default: m_eIcon = KviIconManager::Ban; break; } KviTalHBox * pTitleLayout = new KviTalHBox(this); g->addWidget(pTitleLayout, 0, 0); QLabel * l = new QLabel("", pTitleLayout); l->setPixmap(*(g_pIconManager->getSmallIcon(m_eIcon))); l = new QLabel(szDescription, pTitleLayout); QFrame * pFrame = new QFrame(this); pFrame->setFrameStyle(QFrame::HLine | QFrame::Sunken); g->addWidget(pFrame, 1, 0, 1, -1); KviTalHBox * hb = new KviTalHBox(this); g->addWidget(hb, 2, 0, 1, 2); new QLabel(__tr2qs("Filter:"), hb); m_pSearch = new QLineEdit(hb); connect(m_pSearch, SIGNAL(textChanged(const QString &)), this, SLOT(searchTextChanged(const QString &))); l = new QLabel(__tr2qs("Use double-click to edit item"), this); g->addWidget(l, 2, 1); g->addWidget(l, 3, 0, 1, 2); m_pMaskBox = new QTreeWidget(this); m_pMaskBox->setFocusPolicy(Qt::ClickFocus); m_pMaskBox->setFocusProxy(this); m_pMaskBox->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); m_pMaskBox->setSelectionMode(QAbstractItemView::ExtendedSelection); QStringList columnLabels; m_pMaskBox->setColumnCount(3); columnLabels.append(__tr2qs("Mask")); columnLabels.append(__tr2qs("Set by")); columnLabels.append(__tr2qs("Set at")); m_pMaskBox->setHeaderLabels(columnLabels); m_pMaskBox->setAllColumnsShowFocus(true); m_pMaskBox->setSortingEnabled(true); connect(m_pMaskBox, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem *, int))); g->addWidget(m_pMaskBox, 4, 0, 1, 2); m_pRemoveMask = new QPushButton(__tr2qs("Re&move"), this); m_pRemoveMask->setFocusPolicy(Qt::ClickFocus); m_pRemoveMask->setFocusProxy(this); g->addWidget(m_pRemoveMask, 5, 1); connect(m_pRemoveMask, SIGNAL(clicked()), this, SLOT(removeClicked())); m_pRemoveMask->setIcon(*(g_pIconManager->getSmallIcon(KviIconManager::DeleteItem))); m_pAddButton = new QPushButton(__tr2qs("&Add"), this); g->addWidget(m_pAddButton, 5, 0); connect(m_pAddButton, SIGNAL(clicked()), this, SLOT(addClicked())); m_pAddButton->setIcon(*(g_pIconManager->getSmallIcon(KviIconManager::NewItem))); g->setColumnStretch(1, 1); if(m_pChannel && (!m_pChannel->connection())) { m_pRemoveMask->setEnabled(false); m_pAddButton->setEnabled(false); return; } for(auto & e : maskList) addMask(e); updateOpStatus(); if(m_pChannel) connect(m_pChannel, SIGNAL(opStatusChanged()), this, SLOT(updateOpStatus())); }
void KviModeWidget::editorReturnPressed() { QMap<char, QString> szPlusModes; QMap<char, QString> szMinusModes; QString szTmpMode; m_pChannel->getChannelModeStringWithEmbeddedParams(szTmpMode); QStringList szOldModes=szTmpMode.split(QChar(' '), QString::SkipEmptyParts); QStringList szNewModes=text().split(QChar(' '), QString::SkipEmptyParts); //add new modes and modified ones for(int i=0; i<szNewModes.count(); ++i) { QString szSubstring=szNewModes.at(i); if(i) { // not first part: mode with parameter if(szSubstring.size() < 3) continue; if(szSubstring.at(1) != QChar(':')) continue; char cMode = szSubstring.at(0).unicode(); szSubstring.remove(0,2); if(!m_pChannel->hasChannelMode(cMode) || (szSubstring != m_pChannel->channelModeParam(cMode))) { // mode was not set before, or the parameter has changed szPlusModes.insert(cMode, szSubstring); } } else { // first part: parameterless modes QString szCurModes = szOldModes.count() ? szOldModes.at(0) : ""; for(int j=0; j<szSubstring.length(); ++j) { char cMode = szSubstring.at(j).unicode(); if(!szCurModes.contains(cMode)) { // was not set, has to be inserted szPlusModes.insert(cMode,QString()); } } } } // check for any mode that has been unset for(int i=0; i<szOldModes.count(); ++i) { QString szSubstring=szOldModes.at(i); if(i) { // not first part: mode with parameter if(szSubstring.size() < 3) continue; if(szSubstring.at(1) != QChar(':')) continue; char cMode = szSubstring.at(0).unicode(); szSubstring.remove(0,2); // we skip parameterless modes (j=0) bool bStillSet=false; for(int j=1; j<szNewModes.length(); ++j) { if(szNewModes.at(j).at(0) == cMode) bStillSet=true; } if(!bStillSet) { // checks if this specific mode does not need a parameter when set if(modeNeedsParameterOnlyWhenSet(cMode)) { szMinusModes.insert(cMode,QString()); } else { szMinusModes.insert(cMode, szSubstring); } } } else { // first part: parameterless modes QString szNewParameterLessModes = szNewModes.count() ? szNewModes.at(0) : ""; for(int j=0; j<szSubstring.length(); ++j) { char cMode = szSubstring.at(j).unicode(); if(!szNewParameterLessModes.contains(cMode)) { // was set, has to be unset szMinusModes.insert(cMode,QString()); } } } } // now flush out mode changes int iModesPerLine=3; // a good default KviIrcConnectionServerInfo * pServerInfo = 0; if(m_pChannel) pServerInfo = m_pChannel->serverInfo(); if(pServerInfo) { iModesPerLine = pServerInfo->maxModeChanges(); if(iModesPerLine < 1) iModesPerLine = 1; } QString szModes; QStringList szParameters; int iModes=0; QMap<char, QString>::const_iterator iter = szMinusModes.constBegin(); while (iter != szMinusModes.constEnd()) { if(iter == szMinusModes.constBegin()) szModes.append("-"); szModes.append(iter.key()); szParameters.append(iter.value()); ++iModes; ++iter; //time to commit? if(iModes == iModesPerLine) { QString szCommitModes = szModes; if(iter == szMinusModes.constEnd()) szModes.clear(); else szModes="-"; if(szParameters.count()) { szCommitModes.append(QChar(' ')); szCommitModes.append(szParameters.join(QString(" "))); szParameters.clear(); } iModes=0; emit setMode(szCommitModes); } } iter = szPlusModes.constBegin(); while (iter != szPlusModes.constEnd()) { if(iter == szPlusModes.constBegin()) szModes.append("+"); szModes.append(iter.key()); szParameters.append(iter.value()); ++iModes; ++iter; //time to commit? this should be an ==, but includes the minus sign so "+aaa" = 4 chars if(iModes == iModesPerLine) { QString szCommitModes = szModes; if(iter == szPlusModes.constEnd()) szModes.clear(); else szModes="+"; if(szParameters.count()) { szCommitModes.append(QChar(' ')); szCommitModes.append(szParameters.join(QString(" "))); szParameters.clear(); } iModes=0; emit setMode(szCommitModes); } } if(iModes) { QString szCommitModes = szModes; szModes.clear(); if(szParameters.count()) { szCommitModes.append(QChar(' ')); szCommitModes.append(szParameters.join(QString(" "))); szParameters.clear(); } emit setMode(szCommitModes); } reset(); }