diff --git a/src/svnfrontend/EditIgnorePattern.h b/src/svnfrontend/EditIgnorePattern.h index b3f8b2ac..a7a18748 100644 --- a/src/svnfrontend/EditIgnorePattern.h +++ b/src/svnfrontend/EditIgnorePattern.h @@ -1,44 +1,44 @@ /*************************************************************************** * Copyright (C) 2006-2010 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef EDITIGNOREPATTERN_H_ #define EDITIGNOREPATTERN_H_ #include "ui_editignorepattern.h" #include "svnqt/svnqttypes.h" #include #include class EditIgnorePattern: public QWidget, public Ui::EditIgnorePattern { Q_OBJECT public: - explicit EditIgnorePattern(QWidget *parent = 0); + explicit EditIgnorePattern(QWidget *parent = nullptr); virtual ~EditIgnorePattern(); QStringList items()const; svn::Depth depth()const; bool unignore()const; }; #endif /* EDITIGNOREPATTERN_H_ */ diff --git a/src/svnfrontend/background/getinfothread.cpp b/src/svnfrontend/background/getinfothread.cpp index 024667f3..53caf8b7 100644 --- a/src/svnfrontend/background/getinfothread.cpp +++ b/src/svnfrontend/background/getinfothread.cpp @@ -1,120 +1,120 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht ral@alwins-world.de * * http://kdesvn.alwins-world.de/ * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "getinfothread.h" #include "svnfrontend/models/svnitemnode.h" #include "tcontextlistener.h" #include "svnqt/status.h" #include "svnqt/url.h" #include #include #include GetInfoThread::GetInfoThread(QObject *_parent) : SvnThread(_parent), m_NodeQueue(), m_Cancel(false), m_QueueLock(), m_CancelLock() { } GetInfoThread::~GetInfoThread() { } void GetInfoThread::run() { svn::InfoEntry info; svn::Revision rev = svn::Revision::UNDEFINED; try { while (1) { { QReadLocker cl(&m_CancelLock); if (m_Cancel) { break; } } - SvnItemModelNode *current = 0; + SvnItemModelNode *current = nullptr; { QMutexLocker ml(&m_QueueLock); if (!m_NodeQueue.isEmpty()) { current = m_NodeQueue.dequeue(); } } if (current) { if (!current->hasToolTipText()) { if (current->isRealVersioned() && !current->stat()->entry().url().isEmpty()) { if (svn::Url::isValid(current->fullName())) { rev = current->revision(); } else { rev = svn::Revision::UNDEFINED; } itemInfo(current->fullName(), info, rev, current->correctPeg()); } current->generateToolTip(info); } } else { break; } } } catch (const svn::Exception &e) { m_SvnContextListener->contextNotify(e.msg()); } } void GetInfoThread::cancelMe() { SvnThread::cancelMe(); { QWriteLocker cl(&m_CancelLock); m_Cancel = true; } } void GetInfoThread::appendNode(SvnItemModelNode *node) { if (!node) { return; } QMutexLocker ml(&m_QueueLock); bool found = false; QQueue::const_iterator it = m_NodeQueue.constBegin(); for (; it != m_NodeQueue.constEnd(); ++it) { if ((*it)->fullName() == node->fullName()) { found = true; break; } } if (!found) { m_NodeQueue.enqueue(node); } m_SvnContextListener->setCanceled(false); if (!isRunning()) { { QWriteLocker cl(&m_CancelLock); m_Cancel = false; } start(); } } void GetInfoThread::clearNodes() { QMutexLocker ml(&m_QueueLock); m_NodeQueue.clear(); } diff --git a/src/svnfrontend/background/svnthread.cpp b/src/svnfrontend/background/svnthread.cpp index 8d497eff..d977d7c8 100644 --- a/src/svnfrontend/background/svnthread.cpp +++ b/src/svnfrontend/background/svnthread.cpp @@ -1,83 +1,83 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht ral@alwins-world.de * * http://kdesvn.alwins-world.de/ * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "svnthread.h" #include "tcontextlistener.h" #include "svnqt/url.h" SvnThread::SvnThread(QObject *_parent) : QThread() , m_CurrentContext(new svn::Context) , m_Svnclient(svn::Client::getobject(m_CurrentContext)) , m_SvnContextListener(new ThreadContextListener(_parent)) , m_Parent(_parent) { if (m_Parent) { QObject::connect(m_SvnContextListener, SIGNAL(sendNotify(QString)), m_Parent, SLOT(slotNotifyMessage(QString))); } m_CurrentContext->setListener(m_SvnContextListener); } SvnThread::~SvnThread() { - m_CurrentContext->setListener(0); + m_CurrentContext->setListener(nullptr); delete m_SvnContextListener; } void SvnThread::cancelMe() { m_SvnContextListener->setCanceled(true); } void SvnThread::itemInfo(const QString &what, svn::InfoEntry &target, const svn::Revision &_rev, const svn::Revision &_peg) { QString url, cacheKey; svn::Revision rev = _rev; svn::Revision peg = _peg; if (!svn::Url::isValid(what)) { // working copy // url = svn::Wc::getUrl(what); url = what; if (url.contains(QLatin1Char('@'))) { url += QStringLiteral("@BASE"); } peg = svn::Revision::UNDEFINED; cacheKey = url; } else { // valid url QUrl _uri(what); _uri.setScheme(svn::Url::transformProtokoll(_uri.scheme())); url = _uri.toString(); if (peg == svn::Revision::UNDEFINED) { peg = rev; } if (peg == svn::Revision::UNDEFINED) { peg = svn::Revision::HEAD; } } const svn::InfoEntries _e = (m_Svnclient->info(url, svn::DepthEmpty, rev, peg)); if (!_e.isEmpty()) { target = _e[0]; } } diff --git a/src/svnfrontend/blamedisplay.cpp b/src/svnfrontend/blamedisplay.cpp index 4ba23253..2d875026 100644 --- a/src/svnfrontend/blamedisplay.cpp +++ b/src/svnfrontend/blamedisplay.cpp @@ -1,436 +1,436 @@ /*************************************************************************** * Copyright (C) 2006-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "blamedisplay.h" #include "ui_blamedisplay.h" #include "simple_logcb.h" #include "settings/kdesvnsettings.h" #include "svnqt/log_entry.h" #include "fronthelpers/cursorstack.h" #include "ksvnwidgets/encodingselector_impl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #define COL_LINENR 0 #define COL_REV 1 #define COL_DATE 2 #define COL_AUT 3 #define COL_LINE 4 #define TREE_ITEM_TYPE QTreeWidgetItem::UserType+1 #define BORDER 4 class LocalizedAnnotatedLine: public svn::AnnotateLine { public: explicit LocalizedAnnotatedLine(const svn::AnnotateLine &al) : svn::AnnotateLine(al) {} void localeChanged() { if (!codec_searched) { cc = QTextCodec::codecForName(Kdesvnsettings::locale_for_blame().toLocal8Bit()); codec_searched = true; } if (cc) { m_tLine = cc->toUnicode(line().data(), line().size()); m_tAuthor = cc->toUnicode(author().data(), author().size()); } else { m_tLine = QString::fromUtf8(line().data(), line().size()); m_tAuthor = QString::fromUtf8(author().data(), author().size()); } } const QString &tAuthor()const { return m_tAuthor; } const QString &tLine()const { return m_tLine; } static void reset_codec() { codec_searched = false; - cc = 0; + cc = nullptr; } protected: QString m_tAuthor, m_tLine; static bool codec_searched; static QTextCodec *cc; }; -QTextCodec *LocalizedAnnotatedLine::cc = 0; +QTextCodec *LocalizedAnnotatedLine::cc = nullptr; bool LocalizedAnnotatedLine::codec_searched = false; class BlameTreeItem: public QTreeWidgetItem { public: BlameTreeItem(const svn::AnnotateLine &al, bool disp) : QTreeWidgetItem(TREE_ITEM_TYPE) , m_Content(al) , m_disp(disp) { for (int i = 0; i <= COL_LINE; ++i) { setTextAlignment(i, Qt::AlignLeft | Qt::AlignVCenter); setFont(i, QFontDatabase::systemFont(QFontDatabase::FixedFont)); } display(); } qlonglong lineNumber() const { return m_Content.lineNumber(); } svn_revnum_t rev() const { return m_Content.revision(); } void localeChanged() { m_Content.localeChanged(); if (m_disp) { setText(COL_AUT, m_Content.tAuthor()); } QString _line = m_Content.tLine(); _line.replace(QLatin1Char('\t'), QLatin1String(" ")); setText(COL_LINE, _line); } protected: LocalizedAnnotatedLine m_Content; bool m_disp; void display(); }; void BlameTreeItem::display() { setTextAlignment(COL_LINENR, Qt::AlignRight | Qt::AlignVCenter); if (m_disp) { setTextAlignment(COL_REV, Qt::AlignRight | Qt::AlignVCenter); setText(COL_REV, QString::number(m_Content.revision())); if (m_Content.date().isValid()) { setText(COL_DATE, m_Content.date().toString(Qt::SystemLocaleShortDate)); } } setText(COL_LINENR, QString::number(m_Content.lineNumber() + 1)); localeChanged(); } class BlameDisplayData { public: BlameDisplayData() : max(-1) , min(INT_MAX - 1) , rev_count(0) , up(false) , m_cb(nullptr) , m_pbGoToLine(nullptr) , m_pbShowLog(nullptr) {} svn_revnum_t max, min; QMap m_shadingMap; QMap m_logCache; QColor m_lastCalcColor; unsigned int rev_count; bool up; SimpleLogCb *m_cb; QString m_File; QString reposRoot; QPushButton *m_pbGoToLine; QPushButton *m_pbShowLog; }; BlameDisplay::BlameDisplay(const QString &what, const svn::AnnotatedFile &blame, SimpleLogCb *cb, QWidget *parent) : KSvnDialog(QLatin1String("blame_display_dlg"), parent) , m_ui(new Ui::BlameDisplay) , m_Data(new BlameDisplayData) { m_ui->setupUi(this); m_Data->m_cb = cb; m_Data->m_pbShowLog = new QPushButton(QIcon::fromTheme(QStringLiteral("kdesvnlog")), i18n("Log message for revision"), this); connect(m_Data->m_pbShowLog, SIGNAL(clicked(bool)), this, SLOT(slotShowCurrentCommit())); m_ui->buttonBox->addButton(m_Data->m_pbShowLog, QDialogButtonBox::ActionRole); m_Data->m_pbGoToLine = new QPushButton(i18n("Go to line"), this); connect(m_Data->m_pbGoToLine, SIGNAL(clicked(bool)), this, SLOT(slotGoLine())); m_ui->buttonBox->addButton(m_Data->m_pbGoToLine, QDialogButtonBox::ActionRole); connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(accept())); QAction *ac = new QAction(QIcon::fromTheme(QStringLiteral("kdesvnlog")), i18n("Log message for revision"), this); connect(ac, SIGNAL(triggered()), this, SLOT(slotShowCurrentCommit())); m_ui->m_BlameTree->addAction(ac); KTreeWidgetSearchLine *searchLine = m_ui->m_TreeSearch->searchLine(); searchLine->addTreeWidget(m_ui->m_BlameTree); connect(m_ui->m_BlameTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(slotItemDoubleClicked(QTreeWidgetItem*,int))); connect(m_ui->m_BlameTree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(slotCurrentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*))); connect(m_ui->m_encodingSel, SIGNAL(TextCodecChanged(QString)), this, SLOT(slotTextCodecChanged(QString))); setContent(what, blame); } BlameDisplay::~BlameDisplay() { delete m_Data; delete m_ui; } void BlameDisplay::setContent(const QString &what, const svn::AnnotatedFile &blame) { m_Data->m_File = what; m_Data->m_pbShowLog->setEnabled(false); svn::AnnotatedFile::const_iterator bit; //m_BlameList->setSorting(COL_LINENR,false); m_Data->max = -1; svn_revnum_t lastRev(-1); QColor a(160, 160, 160); int offset = 10; int r = 0; int g = 0; int b = 0; uint colinc = 0; QTime t; t.start(); QList _list; _list.reserve(blame.size()); QBrush _b, _bt, _bb; bool _b_init = false, _bt_init = false; for (bit = blame.begin(); bit != blame.end(); ++bit) { bool disp = (*bit).revision() != lastRev || bit == blame.begin() ; if ((*bit).revision() > m_Data->max) { m_Data->max = (*bit).revision(); ++(m_Data->rev_count); } if ((*bit).revision() < m_Data->min) { m_Data->min = (*bit).revision(); } BlameTreeItem *item = new BlameTreeItem((*bit), disp); _list.append(item); if (disp) { lastRev = (*bit).revision(); } if (Kdesvnsettings::self()->colored_blame()) { if (m_Data->m_shadingMap.find((*bit).revision()) == m_Data->m_shadingMap.end()) { a.setRgb(a.red() + offset, a.green() + offset, a.blue() + offset); m_Data->m_shadingMap[(*bit).revision()] = a; if (a.red() > 245 || a.green() > 245 || a.blue() > 245) { if (colinc == 0) { ++colinc; } else if (r >= 50 || g >= 50 || b >= 50) { if (++colinc > 6) { colinc = 0; r = g = b = 0; } else { r = g = b = -10; } } if (colinc & 0x1) { r += 10; } if (colinc & 0x2) { g += 10; } if (colinc & 0x4) { b += 10; } a.setRgb(160 + r, 160 + g, 160 + b); } } if (!_b_init) { _b_init = true; _b = item->foreground(COL_LINENR); _b.setColor(KColorScheme(QPalette::Active, KColorScheme::Selection).foreground().color()); _bb = item->background(COL_LINENR); _b.setStyle(Qt::SolidPattern); _bb.setStyle(Qt::SolidPattern); _bb.setColor(KColorScheme(QPalette::Active, KColorScheme::Selection).background().color()); } item->setForeground(COL_LINENR, _b); item->setBackground(COL_LINENR, _bb); if (!_bt_init) { _bt_init = true; _bt = item->background(COL_REV); _bt.setStyle(Qt::SolidPattern); } _bt.setColor(m_Data->m_shadingMap.value((*bit).revision())); item->setBackground(COL_REV, _bt); item->setBackground(COL_DATE, _bt); item->setBackground(COL_AUT, _bt); item->setBackground(COL_LINE, _bt); } else { m_Data->m_shadingMap[(*bit).revision()] = QColor(); } } m_ui->m_BlameTree->addTopLevelItems(_list); qDebug("Time elapsed: %d ms", t.elapsed()); m_ui->m_BlameTree->resizeColumnToContents(COL_REV); m_ui->m_BlameTree->resizeColumnToContents(COL_DATE); m_ui->m_BlameTree->resizeColumnToContents(COL_AUT); m_ui->m_BlameTree->resizeColumnToContents(COL_LINENR); m_ui->m_BlameTree->resizeColumnToContents(COL_LINE); } void BlameDisplay::slotGoLine() { bool ok = true; int line = QInputDialog::getInt(this, i18n("Show line"), i18n("Show line number"), 1, 1, m_ui->m_BlameTree->topLevelItemCount(), 1, &ok); if (!ok) { return; } QTreeWidgetItemIterator it(m_ui->m_BlameTree); --line; while (*it) { BlameTreeItem *_it = static_cast((*it)); if (_it->lineNumber() == line) { m_ui->m_BlameTree->scrollToItem(*it); m_ui->m_BlameTree->setCurrentItem(*it); return; } ++it; } } void BlameDisplay::showCommit(BlameTreeItem *bti) { if (!bti) { return; } QString text; const QMap::const_iterator it = m_Data->m_logCache.constFind(bti->rev()); if (it != m_Data->m_logCache.constEnd()) { text = it.value().message; } else { CursorStack a(Qt::BusyCursor); svn::LogEntry t; if (m_Data->m_cb && m_Data->m_cb->getSingleLog(t, bti->rev(), m_Data->m_File, m_Data->max, m_Data->reposRoot)) { m_Data->m_logCache[bti->rev()] = t; text = t.message; } } QPointer dlg(new KSvnDialog(QLatin1String("simplelog_display"), this)); dlg->setWindowTitle(i18nc("@title:window", "Log Message for Revision %1", bti->rev())); QVBoxLayout *vbox = new QVBoxLayout(dlg); KTextEdit *textEdit = new KTextEdit(dlg); vbox->addWidget(textEdit); textEdit->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); textEdit->setReadOnly(true); textEdit->setWordWrapMode(QTextOption::NoWrap); textEdit->setPlainText(text); QDialogButtonBox *bbox = new QDialogButtonBox(dlg); bbox->setStandardButtons(QDialogButtonBox::Close); vbox->addWidget(bbox); // QDialogButtonBox::Close is a reject role connect(bbox, SIGNAL(rejected()), dlg, SLOT(accept())); dlg->exec(); delete dlg; } void BlameDisplay::slotShowCurrentCommit() { QTreeWidgetItem *item = m_ui->m_BlameTree->currentItem(); - if (item == 0 || item->type() != TREE_ITEM_TYPE) { + if (item == nullptr || item->type() != TREE_ITEM_TYPE) { return; } BlameTreeItem *bit = static_cast(item); showCommit(bit); } void BlameDisplay::slotCurrentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *) { const bool enabled = item && item->type() == TREE_ITEM_TYPE; m_Data->m_pbShowLog->setEnabled(enabled); } void BlameDisplay::displayBlame(SimpleLogCb *_cb, const QString &item, const svn::AnnotatedFile &blame, QWidget *parent) { QPointer dlg(new BlameDisplay(item, blame, _cb, parent ? parent : QApplication::activeModalWidget())); dlg->exec(); delete dlg; } void BlameDisplay::slotItemDoubleClicked(QTreeWidgetItem *item, int) { - if (item == 0 || item->type() != TREE_ITEM_TYPE) { + if (item == nullptr || item->type() != TREE_ITEM_TYPE) { return; } BlameTreeItem *bit = static_cast(item); showCommit(bit); } void BlameDisplay::slotTextCodecChanged(const QString &what) { if (Kdesvnsettings::locale_for_blame() != what) { Kdesvnsettings::setLocale_for_blame(what); Kdesvnsettings::self()->save(); LocalizedAnnotatedLine::reset_codec(); QTreeWidgetItemIterator it(m_ui->m_BlameTree); while (*it) { BlameTreeItem *_it = static_cast((*it)); _it->localeChanged(); ++it; } } } diff --git a/src/svnfrontend/ccontextlistener.cpp b/src/svnfrontend/ccontextlistener.cpp index 0eef288a..044bff5f 100644 --- a/src/svnfrontend/ccontextlistener.cpp +++ b/src/svnfrontend/ccontextlistener.cpp @@ -1,406 +1,406 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "ccontextlistener.h" #include "settings/kdesvnsettings.h" #include "ksvnwidgets/authdialogimpl.h" #include "ksvnwidgets/commitmsg_impl.h" #include "ksvnwidgets/ssltrustprompt.h" #include "ksvnwidgets/pwstorage.h" #include "helpers/kdesvn_debug.h" #include #include #include #include #include #include class CContextListenerData { public: CContextListenerData(); virtual ~CContextListenerData(); // data bool m_cancelMe; QMutex m_CancelMutex; bool noDialogs; QStringList m_updatedItems; }; CContextListenerData::CContextListenerData() : m_cancelMe(false), m_CancelMutex(), noDialogs(false), m_updatedItems() { } CContextListenerData::~CContextListenerData() { } const int CContextListener::smax_actionstring = svn_wc_notify_failed_unlock + 1; const char *CContextListener::action_strings[] = { I18N_NOOP("Add to revision control"), I18N_NOOP("Copy"), I18N_NOOP("Delete"), I18N_NOOP("Restore missing"), I18N_NOOP("Revert"), I18N_NOOP("Revert failed"), I18N_NOOP("Resolved"), I18N_NOOP("Skip"), I18N_NOOP("Deleted"), I18N_NOOP("Added"), I18N_NOOP("Update"), //svn_wc_notify_update_update I18N_NOOP("Update complete"), I18N_NOOP("Update external module"), - NULL, // status completed - will not send is just noisy + nullptr, // status completed - will not send is just noisy I18N_NOOP("Status on external"), //svn_wc_notify_status_external I18N_NOOP("Commit Modified"), I18N_NOOP("Commit Added"), I18N_NOOP("Commit Deleted"), I18N_NOOP("Commit Replaced"), - NULL, //tx delta -> making ticks instead - NULL, //svn_wc_notify_blame_revision - using ticks + nullptr, //tx delta -> making ticks instead + nullptr, //svn_wc_notify_blame_revision - using ticks I18N_NOOP("Locking"), I18N_NOOP("Unlocked"), I18N_NOOP("Lock failed"), I18N_NOOP("Unlock failed") }; const char *CContextListener::notify_state_strings[] = { - NULL, // = 0 - NULL, + nullptr, // = 0 + nullptr, I18N_NOOP("unchanged"), I18N_NOOP("item wasn't present"), I18N_NOOP("unversioned item obstructed work"), // I18N_NOOP("Pristine state was modified."), // should send a signal with path instead of message? - NULL, + nullptr, I18N_NOOP("Modified state had mods merged in."), I18N_NOOP("Modified state got conflicting mods.") }; QString CContextListener::NotifyAction(svn_wc_notify_action_t action) { if (action >= smax_actionstring || action < 0) { return QString(); } - return (action_strings[action] == NULL) ? QString() : i18n(action_strings[action]); + return (action_strings[action] == nullptr) ? QString() : i18n(action_strings[action]); } QString CContextListener::NotifyState(svn_wc_notify_state_t state) { if (state > svn_wc_notify_state_conflicted || state < 0) { return QString(); } - return (notify_state_strings[state] == NULL) ? QString() : i18n(notify_state_strings[state]); + return (notify_state_strings[state] == nullptr) ? QString() : i18n(notify_state_strings[state]); } CContextListener::CContextListener(QObject *parent) : QObject(parent) , svn::ContextListener() , m_Data(new CContextListenerData()) { } CContextListener::~CContextListener() { disconnect(); delete m_Data; } bool CContextListener::contextGetCachedLogin(const QString &realm, QString &username, QString &password) { PwStorage::self()->getCachedLogin(realm, username, password); return true; } bool CContextListener::contextGetSavedLogin(const QString &realm, QString &username, QString &password) { if (!Kdesvnsettings::passwords_in_wallet()) { return true; } emit waitShow(true); PwStorage::self()->getLogin(realm, username, password); PwStorage::self()->setCachedLogin(realm, username, password); emit waitShow(false); /* the return value isn't interesting to us... */ return true; } bool CContextListener::contextGetLogin( const QString &realm, QString &username, QString &password, bool &maySave) { bool ret = false; maySave = false; emit waitShow(true); emit sendNotify(realm); QPointer auth(new AuthDialogImpl(realm, username)); if (auth->exec() == QDialog::Accepted) { username = auth->Username(); password = auth->Password(); maySave = (Kdesvnsettings::passwords_in_wallet() ? false : auth->maySave()); if (Kdesvnsettings::passwords_in_wallet() && auth->maySave()) { PwStorage::self()->setLogin(realm, username, password); } if (Kdesvnsettings::use_password_cache()) { PwStorage::self()->setCachedLogin(realm, username, password); } ret = true; } delete auth; emit waitShow(false); return ret; } void CContextListener::contextNotify(const QString &aMsg) { if (aMsg.isEmpty()) { emit tickProgress(); } else { emit sendNotify(aMsg); } } void CContextListener::contextNotify(const char *path, svn_wc_notify_action_t action, svn_node_kind_t /* kind */, const char *mime_type, svn_wc_notify_state_t content_state, svn_wc_notify_state_t prop_state, svn_revnum_t revision) { Q_UNUSED(mime_type); Q_UNUSED(prop_state); QString msg; QString aString = NotifyAction(action); extraNotify(QString::fromUtf8(path), action, revision); if (!aString.isEmpty()) { QTextStream ts(&msg, QIODevice::WriteOnly); ts << NotifyAction(action) << " " << QString::fromUtf8(path); if (revision > -1) { ts << " (Rev " << revision << ")"; } aString = NotifyState(content_state); if (!aString.isEmpty()) { ts << "\n" << aString; } } contextNotify(msg); } void CContextListener::contextNotify(const svn_wc_notify_t *action) { if (!action) { return; } // if (action->actionpath, action->action, action->kind, action->mime_type, action->content_state, action->prop_state, action->revision); // return; // } // QString aString = NotifyAction(action->action); } void CContextListener::sendTick() { emit tickProgress(); } bool CContextListener::contextCancel() { { QMutexLocker lock(&(m_Data->m_CancelMutex)); if (m_Data->m_cancelMe) { m_Data->m_cancelMe = false; return true; } } // otherwise deadlock! sendTick(); return false; } bool CContextListener::contextGetLogMessage(QString &msg, const svn::CommitItemList &items) { bool isOk = false; emit waitShow(true); - QString logMessage = Commitmsg_impl::getLogmessage(items, &isOk, 0, 0, 0); + QString logMessage = Commitmsg_impl::getLogmessage(items, &isOk, nullptr, nullptr, nullptr); if (isOk) { msg = logMessage; } emit waitShow(false); return isOk; } svn::ContextListener::SslServerTrustAnswer CContextListener::contextSslServerTrustPrompt( const svn::ContextListener::SslServerTrustData &data , apr_uint32_t &acceptedFailures) { bool ok, saveit; emit waitShow(true); if (!SslTrustPrompt::sslTrust( data.hostname, data.fingerprint, data.validFrom, data.validUntil, data.issuerDName, data.realm, failure2Strings(acceptedFailures), &ok, &saveit)) { return DONT_ACCEPT; } emit waitShow(false); if (!saveit) { return ACCEPT_TEMPORARILY; } return ACCEPT_PERMANENTLY; } bool CContextListener::contextSslClientCertPrompt(QString &certFile) { qCDebug(KDESVN_LOG) << certFile << endl; emit waitShow(true); QString afile = QFileDialog::getOpenFileName(nullptr, i18n("Open a file with a #PKCS12 certificate")); emit waitShow(false); if (afile.isEmpty()) { return false; } certFile = afile; return true; } bool CContextListener::contextLoadSslClientCertPw(QString &password, const QString &realm) { PwStorage::self()->getCertPw(realm, password); return true; } bool CContextListener::contextSslClientCertPwPrompt(QString &password, const QString &realm, bool &maysave) { maysave = false; emit waitShow(true); QString npass; - QPointer dlg(new KPasswordDialog(0)); + QPointer dlg(new KPasswordDialog(nullptr)); dlg->setPrompt(i18n("Enter password for realm %1", realm)); dlg->setWindowTitle(realm); int res = dlg->exec(); if (res == QDialog::Accepted) { npass = dlg->password(); } bool keepPw = (dlg ? dlg->keepPassword() : false); delete dlg; emit waitShow(false); if (res != QDialog::Accepted) { return false; } maysave = (Kdesvnsettings::passwords_in_wallet() ? false : keepPw); if (Kdesvnsettings::store_passwords() && keepPw) { PwStorage::self()->setCertPw(realm, password); } password = npass; return true; } void CContextListener::setCanceled(bool how) { QMutexLocker lock(&(m_Data->m_CancelMutex)); m_Data->m_cancelMe = how; } QStringList CContextListener::failure2Strings(apr_uint32_t acceptedFailures) { QStringList res; if (acceptedFailures & SVN_AUTH_SSL_UNKNOWNCA) { res << i18n("The certificate is not issued by a trusted authority. Use the fingerprint to validate the certificate manually."); } if (acceptedFailures & SVN_AUTH_SSL_CNMISMATCH) { res << i18n("The certificate hostname does not match."); } if (acceptedFailures & SVN_AUTH_SSL_NOTYETVALID) { res << i18n("The certificate is not yet valid."); } if (acceptedFailures & SVN_AUTH_SSL_EXPIRED) { res << i18n("The certificate has expired."); } if (acceptedFailures & SVN_AUTH_SSL_OTHER) { res << i18n("The certificate has an unknown error."); } return res; } QString CContextListener::translate(const QString &what) { return i18n(what.toLocal8Bit()); } /*! \fn CContextListener::contextProgress(long long int current, long long int max) */ void CContextListener::contextProgress(long long int current, long long int max) { emit netProgress(current, max); } void CContextListener::maySavePlaintext(svn_boolean_t *may_save_plaintext, const QString &realmstring) { emit waitShow(true); if (may_save_plaintext) { QString question = i18n("%1\nReally store password as plain text?", realmstring); QString head = i18n("Save password"); - if (KMessageBox::questionYesNo(0, question, head) == KMessageBox::Yes) { + if (KMessageBox::questionYesNo(nullptr, question, head) == KMessageBox::Yes) { *may_save_plaintext = true; } else { *may_save_plaintext = false; } } emit waitShow(false); } const QStringList &CContextListener::updatedItems()const { return m_Data->m_updatedItems; } void CContextListener::cleanUpdatedItems() { m_Data->m_updatedItems.clear(); } void CContextListener::extraNotify(const QString &path, svn_wc_notify_action_t action, svn_revnum_t revision) { Q_UNUSED(revision); switch (action) { case svn_wc_notify_update_update: case svn_wc_notify_update_add: case svn_wc_notify_update_delete: m_Data->m_updatedItems.append(path); break; default: break; } } diff --git a/src/svnfrontend/ccontextlistener.h b/src/svnfrontend/ccontextlistener.h index 7ee29bf9..0eb9e6ee 100644 --- a/src/svnfrontend/ccontextlistener.h +++ b/src/svnfrontend/ccontextlistener.h @@ -1,106 +1,106 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef CCONTEXTLISTENER_H #define CCONTEXTLISTENER_H #include "svnqt/context_listener.h" #include #include class CContextListenerData; /** @author Rajko Albrecht */ class CContextListener : public QObject, public svn::ContextListener { Q_OBJECT public: - explicit CContextListener(QObject *parent = 0); + explicit CContextListener(QObject *parent = nullptr); virtual ~CContextListener(); /* context-listener methods */ virtual bool contextGetLogin(const QString &realm, QString &username, QString &password, bool &maySave); virtual bool contextGetSavedLogin(const QString &realm, QString &username, QString &password); virtual bool contextGetCachedLogin(const QString &realm, QString &username, QString &password); virtual void contextNotify(const char *path, svn_wc_notify_action_t action, svn_node_kind_t kind, const char *mime_type, svn_wc_notify_state_t content_state, svn_wc_notify_state_t prop_state, svn_revnum_t revision); virtual void contextNotify(const svn_wc_notify_t *action); virtual void contextNotify(const QString &); virtual void sendTick(); virtual bool contextCancel(); /*! * Get logmessage for checkin and so on... */ virtual bool contextGetLogMessage(QString &msg, const svn::CommitItemList &); virtual SslServerTrustAnswer contextSslServerTrustPrompt(const SslServerTrustData &data, apr_uint32_t &acceptedFailures); virtual bool contextSslClientCertPrompt(QString &certFile); virtual bool contextSslClientCertPwPrompt(QString &password, const QString &realm, bool &maySave); virtual bool contextLoadSslClientCertPw(QString &password, const QString &realm); virtual QString translate(const QString &what); static QString NotifyAction(svn_wc_notify_action_t action); static QString NotifyState(svn_wc_notify_state_t); static QStringList failure2Strings(apr_uint32_t acceptedFailures); virtual void contextProgress(long long int current, long long int max); virtual void maySavePlaintext(svn_boolean_t *may_save_plaintext, const QString &realmstring); // used by SvnActions //! get list of updated items when svn update is called const QStringList &updatedItems()const; //! cleans list of updatedItems, should called before calling svn::Client::update void cleanUpdatedItems(); public Q_SLOTS: virtual void setCanceled(bool); Q_SIGNALS: void sendNotify(const QString &); void tickProgress(); void waitShow(bool); void netProgress(long long int, long long int); protected: static const int smax_actionstring; static const char *action_strings[]; static const char *notify_state_strings[]; CContextListenerData *m_Data; private: void extraNotify(const QString &path, svn_wc_notify_action_t action, svn_revnum_t revision); }; #endif diff --git a/src/svnfrontend/commandexec.cpp b/src/svnfrontend/commandexec.cpp index 320fe161..e75f9760 100644 --- a/src/svnfrontend/commandexec.cpp +++ b/src/svnfrontend/commandexec.cpp @@ -1,642 +1,642 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "commandexec.h" #include "settings/kdesvnsettings.h" #include "svnfrontend/svnactions.h" #include "svnfrontend/dummydisplay.h" #include "svnqt/targets.h" #include "svnqt/url.h" #include "svnqt/dirent.h" #include "helpers/ktranslateurl.h" #include "helpers/sshagent.h" #include "helpers/windowgeometryhelper.h" #include "svnfrontend/fronthelpers/rangeinput_impl.h" #include "svnfrontend/copymoveview_impl.h" #include "ksvnwidgets/ksvndialog.h" #include #include #include #include #include #include class pCPart { public: pCPart(); ~pCPart(); QString cmd; QStringList urls; bool ask_revision; bool rev_set; bool outfile_set; bool single_revision; bool force; int log_limit; SvnActions *m_SvnWrapper; QCommandLineParser *parser; QStringList args; svn::Revision start, end; // for output QString outfile; QTextStream Stdout, Stderr; DummyDisplay *disp; QMap extraRevisions; QMap repoUrls; }; pCPart::pCPart() : cmd() , urls() , ask_revision(false) , rev_set(false) , outfile_set(false) , single_revision(false) , force(false) , log_limit(0) - , m_SvnWrapper(NULL) - , parser(NULL) + , m_SvnWrapper(nullptr) + , parser(nullptr) , start(svn::Revision::UNDEFINED) , end(svn::Revision::UNDEFINED) , Stdout(stdout) , Stderr(stderr) , disp(new DummyDisplay()) { m_SvnWrapper = new SvnActions(disp, true); } pCPart::~pCPart() { delete m_SvnWrapper; delete disp; } CommandExec::CommandExec(QObject *parent) : QObject(parent) , m_lastMessagesLines(0) { m_pCPart = new pCPart; - m_pCPart->parser = 0; + m_pCPart->parser = nullptr; SshAgent ag; ag.querySshAgent(); connect(m_pCPart->m_SvnWrapper, SIGNAL(clientException(QString)), this, SLOT(clientException(QString))); connect(m_pCPart->m_SvnWrapper, SIGNAL(sendNotify(QString)), this, SLOT(slotNotifyMessage(QString))); m_pCPart->m_SvnWrapper->reInitClient(); } CommandExec::~CommandExec() { delete m_pCPart; } int CommandExec::exec(const QCommandLineParser *parser) { m_pCPart->parser = const_cast(parser); m_pCPart->args = parser->positionalArguments(); if (m_pCPart->args.isEmpty()) { return -1; } m_lastMessages.clear(); m_lastMessagesLines = 0; m_pCPart->m_SvnWrapper->reInitClient(); bool dont_check_second = false; bool dont_check_all = false; bool path_only = false; bool no_revision = false; bool check_force = false; if (m_pCPart->args.count() >= 2) { m_pCPart->cmd = m_pCPart->args.at(1); m_pCPart->cmd = m_pCPart->cmd.toLower(); } QByteArray slotCmd; if (!QString::compare(m_pCPart->cmd, QLatin1String("log"))) { slotCmd = SLOT(slotCmd_log()); } else if (!QString::compare(m_pCPart->cmd, QLatin1String("cat"))) { slotCmd = SLOT(slotCmd_cat()); m_pCPart->single_revision = true; } else if (!QString::compare(m_pCPart->cmd, QLatin1String("get"))) { slotCmd = SLOT(slotCmd_get()); m_pCPart->single_revision = true; } else if (!QString::compare(m_pCPart->cmd, QLatin1String("help"))) { slotCmd = SLOT(slotCmd_help()); } else if (!QString::compare(m_pCPart->cmd, QLatin1String("blame")) || !QString::compare(m_pCPart->cmd, QLatin1String("annotate"))) { slotCmd = SLOT(slotCmd_blame()); } else if (!QString::compare(m_pCPart->cmd, QLatin1String("update"))) { slotCmd = SLOT(slotCmd_update()); m_pCPart->single_revision = true; } else if (!QString::compare(m_pCPart->cmd, QLatin1String("diff"))) { m_pCPart->start = svn::Revision::WORKING; slotCmd = SLOT(slotCmd_diff()); } else if (!QString::compare(m_pCPart->cmd, QLatin1String("info"))) { slotCmd = SLOT(slotCmd_info()); m_pCPart->single_revision = true; } else if (!QString::compare(m_pCPart->cmd, QLatin1String("commit")) || !QString::compare(m_pCPart->cmd, QLatin1String("ci"))) { slotCmd = SLOT(slotCmd_commit()); } else if (!QString::compare(m_pCPart->cmd, QLatin1String("list")) || !QString::compare(m_pCPart->cmd, QLatin1String("ls"))) { slotCmd = SLOT(slotCmd_list()); } else if (!QString::compare(m_pCPart->cmd, QLatin1String("copy")) || !QString::compare(m_pCPart->cmd, QLatin1String("cp"))) { slotCmd = SLOT(slotCmd_copy()); dont_check_second = true; } else if (!QString::compare(m_pCPart->cmd, QLatin1String("move")) || !QString::compare(m_pCPart->cmd, QLatin1String("rename")) || !QString::compare(m_pCPart->cmd, QLatin1String("mv"))) { slotCmd = SLOT(slotCmd_move()); dont_check_second = true; } else if (!QString::compare(m_pCPart->cmd, QLatin1String("checkout")) || !QString::compare(m_pCPart->cmd, QLatin1String("co"))) { slotCmd = SLOT(slotCmd_checkout()); dont_check_second = true; } else if (!QString::compare(m_pCPart->cmd, QLatin1String("checkoutto")) || !QString::compare(m_pCPart->cmd, QLatin1String("coto"))) { slotCmd = SLOT(slotCmd_checkoutto()); dont_check_second = true; } else if (!QString::compare(m_pCPart->cmd, QLatin1String("export"))) { slotCmd = SLOT(slotCmd_export()); dont_check_second = true; } else if (!QString::compare(m_pCPart->cmd, QLatin1String("exportto"))) { slotCmd = SLOT(slotCmd_exportto()); dont_check_second = true; } else if (!QString::compare(m_pCPart->cmd, QLatin1String("delete")) || !QString::compare(m_pCPart->cmd, QLatin1String("del")) || !QString::compare(m_pCPart->cmd, QLatin1String("rm")) || !QString::compare(m_pCPart->cmd, QLatin1String("remove"))) { slotCmd = SLOT(slotCmd_delete()); } else if (!QString::compare(m_pCPart->cmd, QLatin1String("add"))) { slotCmd = SLOT(slotCmd_add()); dont_check_all = true; path_only = true; } else if (!QString::compare(m_pCPart->cmd, QLatin1String("undo")) || !QString::compare(m_pCPart->cmd, QLatin1String("revert"))) { slotCmd = SLOT(slotCmd_revert()); } else if (!QString::compare(m_pCPart->cmd, QLatin1String("checknew")) || !QString::compare(m_pCPart->cmd, QLatin1String("addnew"))) { slotCmd = SLOT(slotCmd_addnew()); } else if (!QString::compare(m_pCPart->cmd, QLatin1String("switch"))) { slotCmd = SLOT(slotCmd_switch()); } else if (!QString::compare(m_pCPart->cmd, QLatin1String("tree"))) { slotCmd = SLOT(slotCmd_tree()); } else if (!QString::compare(m_pCPart->cmd, QLatin1String("lock"))) { slotCmd = SLOT(slotCmd_lock()); no_revision = true; check_force = true; } else if (!QString::compare(m_pCPart->cmd, QLatin1String("unlock"))) { slotCmd = SLOT(slotCmd_unlock()); no_revision = true; check_force = true; } bool found = connect(this, SIGNAL(executeMe()), this, slotCmd.constData()); if (!found) { - KMessageBox::sorry(0, + KMessageBox::sorry(nullptr, i18n("Command \"%1\" not implemented or known", m_pCPart->cmd), i18n("SVN Error")); return -1; } QString tmp; QString mainProto; for (int j = 2; j < m_pCPart->args.count(); ++j) { QUrl tmpurl = QUrl::fromUserInput(m_pCPart->args.at(j), QDir::currentPath()); tmpurl.setScheme(svn::Url::transformProtokoll(tmpurl.scheme())); if (tmpurl.scheme().contains(QLatin1String("ssh"))) { SshAgent ag; // this class itself checks if done before ag.addSshIdentities(); } m_pCPart->extraRevisions[j - 2] = svn::Revision::HEAD; if (tmpurl.isLocalFile() && (j == 2 || !dont_check_second) && !dont_check_all) { QUrl repoUrl; if (m_pCPart->m_SvnWrapper->isLocalWorkingCopy(tmpurl.path(), repoUrl)) { tmp = tmpurl.path(); m_pCPart->repoUrls[j - 2] = repoUrl; m_pCPart->extraRevisions[j - 2] = svn::Revision::WORKING; if (j == 2) { mainProto.clear(); } } else { tmp = tmpurl.url(); if (j == 2) { mainProto = QLatin1String("file://"); } } } else if (path_only) { tmp = tmpurl.path(); } else { tmp = tmpurl.url(); if (j == 2) { mainProto = tmpurl.scheme(); } } if ((j > 2 && dont_check_second) || dont_check_all) { if (mainProto.isEmpty()) { tmp = tmpurl.path(); } } const QVector l = tmp.splitRef(QLatin1Char('?'), QString::SkipEmptyParts); if (!l.isEmpty()) { tmp = l.first().toString(); } while (tmp.endsWith(QLatin1Char('/'))) { tmp.chop(1); } m_pCPart->urls.append(tmp); if ((j > 2 && dont_check_second) || dont_check_all) { continue; } const QList > q = QUrlQuery(tmpurl).queryItems(); for(int i = 0; i < q.size(); ++i) { if (q.at(i).first == QLatin1String("rev")) { svn::Revision re = q.at(i).second; if (re) { m_pCPart->extraRevisions[j - 2] = re; } } } } if (m_pCPart->urls.isEmpty()) { m_pCPart->urls.append(QLatin1String(".")); } if (!no_revision) { if (m_pCPart->parser->isSet("R")) { m_pCPart->ask_revision = true; if (!askRevision()) { return 0; } } else if (m_pCPart->parser->isSet("r")) { scanRevision(); } } m_pCPart->force = check_force && m_pCPart->parser->isSet("f"); if (m_pCPart->parser->isSet("o")) { m_pCPart->outfile_set = true; m_pCPart->outfile = m_pCPart->parser->value("o"); } if (m_pCPart->parser->isSet("l")) { QString s = m_pCPart->parser->value("l"); m_pCPart->log_limit = s.toInt(); if (m_pCPart->log_limit < 0) { m_pCPart->log_limit = 0; } } emit executeMe(); if (Kdesvnsettings::self()->cmdline_show_logwindow() && m_lastMessagesLines >= Kdesvnsettings::self()->cmdline_log_minline()) { QPointer dlg(new KSvnSimpleOkDialog(QStringLiteral("kdesvn_cmd_log"), QApplication::activeModalWidget())); QTextBrowser *ptr = new QTextBrowser(dlg); ptr->setText(m_lastMessages); ptr->setReadOnly(true); dlg->addWidget(ptr); QString cmd = qApp->arguments().join(QLatin1Char(' ')); dlg->setWindowTitle(cmd); dlg->exec(); delete dlg; } return 0; } /*! \fn CommandExec::clientException(const QString&) */ void CommandExec::clientException(const QString &what) { m_pCPart->Stderr << what << endl; - KMessageBox::sorry(0, what, i18n("SVN Error")); + KMessageBox::sorry(nullptr, what, i18n("SVN Error")); } void CommandExec::slotCmd_log() { int limit = m_pCPart->log_limit; if (m_pCPart->end == svn::Revision::UNDEFINED) { m_pCPart->end = svn::Revision::HEAD; } if (m_pCPart->start == svn::Revision::UNDEFINED) { m_pCPart->start = 1; } bool list = Kdesvnsettings::self()->log_always_list_changed_files(); if (m_pCPart->extraRevisions[0] == svn::Revision::WORKING) { m_pCPart->extraRevisions[0] = svn::Revision::UNDEFINED; } m_pCPart->m_SvnWrapper->makeLog(m_pCPart->start, m_pCPart->end, m_pCPart->extraRevisions.value(0), m_pCPart->urls.at(0), Kdesvnsettings::log_follows_nodes(), list, limit); } void CommandExec::slotCmd_tree() { if (m_pCPart->end == svn::Revision::UNDEFINED) { m_pCPart->end = svn::Revision::HEAD; } if (m_pCPart->start == svn::Revision::UNDEFINED) { m_pCPart->start = 1; } m_pCPart->m_SvnWrapper->makeTree(m_pCPart->urls.at(0), m_pCPart->extraRevisions.value(0), m_pCPart->start, m_pCPart->end); } void CommandExec::slotCmd_checkout() { m_pCPart->m_SvnWrapper->CheckoutExport(QUrl::fromUserInput(m_pCPart->urls.at(0), QDir::currentPath()), false); } void CommandExec::slotCmd_checkoutto() { m_pCPart->m_SvnWrapper->CheckoutExport(QUrl::fromUserInput(m_pCPart->urls.at(0), QDir::currentPath()), false, true); } void CommandExec::slotCmd_export() { m_pCPart->m_SvnWrapper->CheckoutExport(QUrl::fromUserInput(m_pCPart->urls.at(0), QDir::currentPath()), true); } void CommandExec::slotCmd_exportto() { m_pCPart->m_SvnWrapper->CheckoutExport(QUrl::fromUserInput(m_pCPart->urls.at(0), QDir::currentPath()), true, true); } void CommandExec::slotCmd_blame() { if (!m_pCPart->end) { m_pCPart->end = svn::Revision::HEAD; } if (!m_pCPart->start) { m_pCPart->start = 1; } m_pCPart->m_SvnWrapper->makeBlame(m_pCPart->start, m_pCPart->end, m_pCPart->urls.at(0)); } void CommandExec::slotCmd_cat() { QMap::const_iterator cIt = m_pCPart->extraRevisions.constFind(0); if (cIt != m_pCPart->extraRevisions.constEnd()) { m_pCPart->rev_set = true; m_pCPart->start = cIt.value(); } else { m_pCPart->end = svn::Revision::HEAD; } m_pCPart->m_SvnWrapper->slotMakeCat( (m_pCPart->rev_set ? m_pCPart->start : m_pCPart->end), m_pCPart->urls.at(0), m_pCPart->urls.at(0) - , (m_pCPart->rev_set ? m_pCPart->start : m_pCPart->end), 0); + , (m_pCPart->rev_set ? m_pCPart->start : m_pCPart->end), nullptr); } void CommandExec::slotCmd_get() { if (m_pCPart->extraRevisions.find(0) != m_pCPart->extraRevisions.end()) { m_pCPart->rev_set = true; m_pCPart->start = m_pCPart->extraRevisions[0]; } else { m_pCPart->end = svn::Revision::HEAD; } if (!m_pCPart->outfile_set || m_pCPart->outfile.isEmpty()) { clientException(i18n("\"GET\" requires output file")); return; } m_pCPart->m_SvnWrapper->makeGet((m_pCPart->rev_set ? m_pCPart->start : m_pCPart->end), m_pCPart->urls.at(0), m_pCPart->outfile, (m_pCPart->rev_set ? m_pCPart->start : m_pCPart->end)); } void CommandExec::slotCmd_update() { const svn::Targets targets = svn::Targets::fromStringList(m_pCPart->urls); m_pCPart->m_SvnWrapper->makeUpdate(targets, (m_pCPart->rev_set ? m_pCPart->start : svn::Revision::HEAD), svn::DepthUnknown); } void CommandExec::slotCmd_diff() { if (m_pCPart->urls.count() == 1) { if (!m_pCPart->rev_set && !svn::Url::isValid(m_pCPart->urls.at(0))) { m_pCPart->start = svn::Revision::BASE; m_pCPart->end = svn::Revision::WORKING; } m_pCPart->m_SvnWrapper->makeDiff(m_pCPart->urls.at(0), m_pCPart->start, m_pCPart->urls.at(0), m_pCPart->end); } else { svn::Revision r1 = svn::Revision::HEAD; svn::Revision r2 = svn::Revision::HEAD; QMap::const_iterator cIt = m_pCPart->extraRevisions.constFind(0); if (cIt != m_pCPart->extraRevisions.constEnd()) { r1 = cIt.value(); } else if (!svn::Url::isValid(m_pCPart->urls.at(0))) { r1 = svn::Revision::WORKING; } if (m_pCPart->extraRevisions.find(1) != m_pCPart->extraRevisions.end()) { r2 = m_pCPart->extraRevisions[1]; } else if (!svn::Url::isValid(m_pCPart->urls.at(1))) { r2 = svn::Revision::WORKING; } m_pCPart->m_SvnWrapper->makeDiff(m_pCPart->urls.at(0), r1, m_pCPart->urls.at(1), r2); } } void CommandExec::slotCmd_info() { QMap::const_iterator cIt = m_pCPart->extraRevisions.constFind(0); if (cIt != m_pCPart->extraRevisions.constEnd()) { m_pCPart->rev_set = true; m_pCPart->start = cIt.value(); } m_pCPart->m_SvnWrapper->makeInfo(m_pCPart->urls, (m_pCPart->rev_set ? m_pCPart->start : m_pCPart->end), svn::Revision::UNDEFINED, false); } void CommandExec::slotCmd_commit() { const svn::Targets targets(svn::Targets::fromStringList(m_pCPart->urls)); m_pCPart->m_SvnWrapper->makeCommit(targets); } void CommandExec::slotCmd_list() { svn::DirEntries res; svn::Revision rev = m_pCPart->end; if (m_pCPart->rev_set) { rev = m_pCPart->start; } else if (m_pCPart->extraRevisions[0]) { rev = m_pCPart->extraRevisions[0]; } if (!m_pCPart->m_SvnWrapper->makeList(m_pCPart->urls.at(0), res, rev, svn::DepthInfinity)) { return; } Q_FOREACH(const svn::DirEntry &entry, res) { QString d = entry.time().toString(QStringLiteral("yyyy-MM-dd hh:mm::ss")); m_pCPart->Stdout << (entry.kind() == svn_node_dir ? "D" : "F") << " " << d << " " << entry.name() << endl; } } void CommandExec::slotCmd_copy() { QString target; if (m_pCPart->urls.count() < 2) { bool ok; target = CopyMoveView_impl::getMoveCopyTo(&ok, false, - m_pCPart->urls.at(0), QString(), 0); + m_pCPart->urls.at(0), QString(), nullptr); if (!ok) { return; } } else { target = m_pCPart->urls.at(1); } QMap::const_iterator cIt = m_pCPart->extraRevisions.constFind(0); if (cIt != m_pCPart->extraRevisions.constEnd()) { m_pCPart->rev_set = true; m_pCPart->start = cIt.value(); } else { m_pCPart->end = svn::Revision::HEAD; } m_pCPart->m_SvnWrapper->makeCopy(m_pCPart->urls.at(0), target, (m_pCPart->rev_set ? m_pCPart->start : m_pCPart->end)); } void CommandExec::slotCmd_move() { bool ok; QString target; if (m_pCPart->urls.count() < 2) { target = CopyMoveView_impl::getMoveCopyTo(&ok, true, - m_pCPart->urls.at(0), QString(), 0); + m_pCPart->urls.at(0), QString(), nullptr); if (!ok) { return; } } else { target = m_pCPart->urls.at(1); } m_pCPart->m_SvnWrapper->makeMove(m_pCPart->urls.at(0), target); } void CommandExec::slotCmd_delete() { m_pCPart->m_SvnWrapper->makeDelete(m_pCPart->urls); } void CommandExec::slotCmd_add() { m_pCPart->m_SvnWrapper->addItems(svn::Targets::fromStringList(m_pCPart->urls), svn::DepthInfinity); } void CommandExec::slotCmd_revert() { m_pCPart->m_SvnWrapper->slotRevertItems(m_pCPart->urls); } void CommandExec::slotCmd_addnew() { m_pCPart->m_SvnWrapper->checkAddItems(m_pCPart->urls.at(0)); } /*! \fn CommandExec::scanRevision() */ bool CommandExec::scanRevision() { const QString revstring = m_pCPart->parser->value(QStringLiteral("r")); const QVector revl = revstring.splitRef(QLatin1Char(':'), QString::SkipEmptyParts); if (revl.isEmpty()) { return false; } m_pCPart->start = revl[0].toString(); if (revl.count() > 1) { m_pCPart->end = revl[1].toString(); } m_pCPart->rev_set = true; return true; } void CommandExec::slotNotifyMessage(const QString &msg) { m_pCPart->m_SvnWrapper->slotExtraLogMsg(msg); if (Kdesvnsettings::self()->cmdline_show_logwindow()) { ++m_lastMessagesLines; if (!m_lastMessages.isEmpty()) { m_lastMessages.append("\n"); } m_lastMessages.append(msg); } } bool CommandExec::askRevision() { bool ret = false; Rangeinput_impl::revision_range range; if (Rangeinput_impl::getRevisionRange(range, true, m_pCPart->single_revision)) { m_pCPart->start = range.first; m_pCPart->end = range.second; m_pCPart->rev_set = true; ret = true; } return ret; } /*! \fn CommandExec::slotCmd_switch() */ void CommandExec::slotCmd_switch() { if (m_pCPart->urls.count() > 1) { clientException(i18n("May only switch one URL at time")); return; } if (m_pCPart->repoUrls.find(0) == m_pCPart->repoUrls.end()) { clientException(i18n("Switch only on working copies")); return; } m_pCPart->m_SvnWrapper->makeSwitch(m_pCPart->urls.at(0), m_pCPart->repoUrls.value(0)); } void CommandExec::slotCmd_lock() { // m_pCPart->m_SvnWrapper->makeLock(m_pCPart->urls.at(0),"",m_pCPart->force); m_pCPart->m_SvnWrapper->makeLock(m_pCPart->urls, QString(), m_pCPart->force); } void CommandExec::slotCmd_unlock() { // m_pCPart->m_SvnWrapper->makeUnlock(m_pCPart->urls.at(0),m_pCPart->force); m_pCPart->m_SvnWrapper->makeUnlock(m_pCPart->urls, m_pCPart->force); } diff --git a/src/svnfrontend/copymoveview_impl.h b/src/svnfrontend/copymoveview_impl.h index 4a0e1de7..a01c8c6c 100644 --- a/src/svnfrontend/copymoveview_impl.h +++ b/src/svnfrontend/copymoveview_impl.h @@ -1,55 +1,55 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef COPYMOVEVIEW_IMPL_H #define COPYMOVEVIEW_IMPL_H #include "ui_copymoveview.h" class CopyMoveView_impl : public QWidget, public Ui::CopyMoveView { Q_OBJECT public: CopyMoveView_impl(const QString &baseName, const QString &sourceName, bool move, QWidget *parent); ~CopyMoveView_impl(); QString newName() const; bool force() const; static QString getMoveCopyTo(bool *ok, bool move, const QString &old, - const QString &base, QWidget *parent = 0); + const QString &base, QWidget *parent = nullptr); /*$PUBLIC_FUNCTIONS$*/ public slots: /*$PUBLIC_SLOTS$*/ protected: /*$PROTECTED_FUNCTIONS$*/ protected slots: /*$PROTECTED_SLOTS$*/ protected: QString m_OldName; QString m_BaseName; }; #endif diff --git a/src/svnfrontend/dummydisplay.cpp b/src/svnfrontend/dummydisplay.cpp index c84fd76b..9b33ca2f 100644 --- a/src/svnfrontend/dummydisplay.cpp +++ b/src/svnfrontend/dummydisplay.cpp @@ -1,62 +1,62 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "dummydisplay.h" #include "svnqt/revision.h" #include DummyDisplay::DummyDisplay() : ItemDisplay() { } DummyDisplay::~DummyDisplay() { } QWidget *DummyDisplay::realWidget() { - return 0L; + return nullptr; } SvnItem *DummyDisplay::Selected()const { - return 0L; + return nullptr; } SvnItemList DummyDisplay::SelectionList()const { return SvnItemList(); } bool DummyDisplay::openUrl(const QUrl &, bool) { return false; } SvnItem *DummyDisplay::SelectedOrMain()const { - return 0; + return nullptr; } svn::Revision DummyDisplay::baseRevision()const { static svn::Revision fake(svn::Revision::UNDEFINED); return fake; } diff --git a/src/svnfrontend/dumprepo_impl.h b/src/svnfrontend/dumprepo_impl.h index 504afdeb..e0795a27 100644 --- a/src/svnfrontend/dumprepo_impl.h +++ b/src/svnfrontend/dumprepo_impl.h @@ -1,41 +1,41 @@ /*************************************************************************** * Copyright (C) 2006-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef DUMPREPO_IMPL_H #define DUMPREPO_IMPL_H #include "ui_dumprepo_dlg.h" class DumpRepo_impl: public QWidget, public Ui::DumpRepoDlg { Q_OBJECT public: - explicit DumpRepo_impl(QWidget *parent = 0); + explicit DumpRepo_impl(QWidget *parent = nullptr); QString reposPath() const; QString targetFile() const; bool incremental() const; bool use_deltas() const; bool useNumbers() const; int startNumber() const; int endNumber() const; protected slots: void slotDumpRange(bool); }; #endif diff --git a/src/svnfrontend/fronthelpers/checkoutinfo_impl.h b/src/svnfrontend/fronthelpers/checkoutinfo_impl.h index 4847899c..fd0ea0f9 100644 --- a/src/svnfrontend/fronthelpers/checkoutinfo_impl.h +++ b/src/svnfrontend/fronthelpers/checkoutinfo_impl.h @@ -1,58 +1,58 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef CHECKOUTINFO_IMPL_H #define CHECKOUTINFO_IMPL_H #include "ui_checkoutinfo.h" #include "svnqt/revision.h" #include "svnqt/svnqttypes.h" class CheckoutInfo_impl: public QWidget, public Ui::CheckoutInfo { Q_OBJECT public: - explicit CheckoutInfo_impl(QWidget *parent = 0); + explicit CheckoutInfo_impl(QWidget *parent = nullptr); virtual ~CheckoutInfo_impl(); svn::Revision toRevision() const; QUrl reposURL() const; QString targetDir() const; bool overwrite() const; svn::Depth getDepth() const; void setStartUrl(const QUrl &); void disableForce(bool how); void disableTargetDir(bool how); void disableAppend(bool how); void disableOpen(bool how); bool openAfterJob() const; void disableRange(bool how); void setTargetUrl(const QUrl &); bool ignoreExternals() const; void hideDepth(bool hide); void hideOverwrite(bool hide); void hideIgnoreKeywords(bool hide); bool ignoreKeywords() const; protected slots: void urlChanged(const QString &); }; #endif diff --git a/src/svnfrontend/fronthelpers/kmultilinedelegate.h b/src/svnfrontend/fronthelpers/kmultilinedelegate.h index 25089fc0..1955ae1a 100644 --- a/src/svnfrontend/fronthelpers/kmultilinedelegate.h +++ b/src/svnfrontend/fronthelpers/kmultilinedelegate.h @@ -1,37 +1,37 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef KMULTILINE_DELEGATE_H #define KMULTILINE_DELEGATE_H #include class KMultilineDelegate : public QItemDelegate { Q_OBJECT public: - explicit KMultilineDelegate(QObject *parent = 0); + explicit KMultilineDelegate(QObject *parent = nullptr); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index)const; }; #endif diff --git a/src/svnfrontend/fronthelpers/watchedprocess.h b/src/svnfrontend/fronthelpers/watchedprocess.h index b79d5ae4..c630b56b 100644 --- a/src/svnfrontend/fronthelpers/watchedprocess.h +++ b/src/svnfrontend/fronthelpers/watchedprocess.h @@ -1,60 +1,60 @@ /*************************************************************************** * Copyright (C) 2008 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include #ifndef WATCHEDPROCESS_H #define WATCHEDPROCESS_H class ProcessData; class WatchedProcess: public KProcess { Q_OBJECT public: - explicit WatchedProcess(QObject *parent = 0); + explicit WatchedProcess(QObject *parent = nullptr); virtual ~WatchedProcess(); void appendTempFile(const QString &); void appendTempDir(const QString &); void setAutoDelete(bool); bool autoDelete()const; private: ProcessData *m_Data; protected Q_SLOTS: void slotError(QProcess::ProcessError); void slotFinished(int, QProcess::ExitStatus); void slotReadyReadStandardError(); void slotReadyReadStandardOutput(); void slotStarted(); void slotStateChanged(QProcess::ProcessState); Q_SIGNALS: void dataStderrRead(const QByteArray &, WatchedProcess *); void dataStdoutRead(const QByteArray &, WatchedProcess *); void error(QProcess::ProcessError, WatchedProcess *); void finished(int, QProcess::ExitStatus, WatchedProcess *); void started(WatchedProcess *); void stateChanged(QProcess::ProcessState newState, WatchedProcess *); }; #endif diff --git a/src/svnfrontend/graphtree/drawparams.cpp b/src/svnfrontend/graphtree/drawparams.cpp index b7ed0cc6..91e02ae9 100644 --- a/src/svnfrontend/graphtree/drawparams.cpp +++ b/src/svnfrontend/graphtree/drawparams.cpp @@ -1,831 +1,831 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht ral@alwins-world.de * * http://kdesvn.alwins-world.de/ * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ /* This file was part of KCachegrind. Copyright (C) 2002, 2003 Josef Weidendorfer Adapted for the needs of kdesvn by Rajko Albrecht */ /* * A Widget for visualizing hierarchical metrics as areas. * The API is similar to QListView. */ #include "drawparams.h" #include #include #include // set this to 1 to enable debug output #define DEBUG_DRAWING 0 #define MAX_FIELD 12 // // StoredDrawParams // StoredDrawParams::StoredDrawParams() { _selected = false; _current = false; _shaded = true; _rotated = false; _drawFrame = false; _backColor = Qt::white; // field array has size 0 } StoredDrawParams::StoredDrawParams(const QColor &c, bool selected, bool current) { _backColor = c; _selected = selected; _current = current; _shaded = true; _rotated = false; _drawFrame = true; // field array has size 0 } QString StoredDrawParams::text(int f) const { if ((f < 0) || (f >= (int)_field.size())) { return QString(); } return _field[f].text; } QPixmap StoredDrawParams::pixmap(int f) const { if ((f < 0) || (f >= (int)_field.size())) { return QPixmap(); } return _field[f].pix; } DrawParams::Position StoredDrawParams::position(int f) const { if ((f < 0) || (f >= (int)_field.size())) { return Default; } return _field[f].pos; } int StoredDrawParams::maxLines(int f) const { if ((f < 0) || (f >= (int)_field.size())) { return 0; } return _field[f].maxLines; } QFont StoredDrawParams::font() const { return QFontDatabase::systemFont(QFontDatabase::FixedFont); } void StoredDrawParams::ensureField(int f) { - static Field *def = 0; + static Field *def = nullptr; if (!def) { def = new Field(); def->pos = Default; def->maxLines = 0; } if (f < 0 || f >= MAX_FIELD) { return; } while (_field.size() < f + 1) { _field.append(*def); } } void StoredDrawParams::setField(int f, const QString &t, const QPixmap &pm, Position p, int maxLines) { if (f < 0 || f >= MAX_FIELD) { return; } ensureField(f); _field[f].text = t; _field[f].pix = pm; _field[f].pos = p; _field[f].maxLines = maxLines; } void StoredDrawParams::setText(int f, const QString &t) { if (f < 0 || f >= MAX_FIELD) { return; } ensureField(f); _field[f].text = t; } void StoredDrawParams::setPixmap(int f, QPixmap pm) { if (f < 0 || f >= MAX_FIELD) { return; } ensureField(f); _field[f].pix = pm; } void StoredDrawParams::setPosition(int f, Position p) { if (f < 0 || f >= MAX_FIELD) { return; } ensureField(f); _field[f].pos = p; } void StoredDrawParams::setMaxLines(int f, int m) { if (f < 0 || f >= MAX_FIELD) { return; } ensureField(f); _field[f].maxLines = m; } // // RectDrawing // RectDrawing::RectDrawing(const QRect &r) { - _fm = 0; - _dp = 0; + _fm = nullptr; + _dp = nullptr; setRect(r); } RectDrawing::~RectDrawing() { delete _fm; delete _dp; } DrawParams *RectDrawing::drawParams() { if (!_dp) { _dp = new StoredDrawParams(); } return _dp; } void RectDrawing::setDrawParams(DrawParams *dp) { if (_dp) { delete _dp; } _dp = dp; } void RectDrawing::setRect(QRect r) { _rect = r; _usedTopLeft = 0; _usedTopCenter = 0; _usedTopRight = 0; _usedBottomLeft = 0; _usedBottomCenter = 0; _usedBottomRight = 0; _fontHeight = 0; } QRect RectDrawing::remainingRect(DrawParams *dp) { if (!dp) { dp = drawParams(); } if ((_usedTopLeft > 0) || (_usedTopCenter > 0) || (_usedTopRight > 0)) { if (dp->rotated()) { _rect.setLeft(_rect.left() + _fontHeight); } else { _rect.setTop(_rect.top() + _fontHeight); } } if ((_usedBottomLeft > 0) || (_usedBottomCenter > 0) || (_usedBottomRight > 0)) { if (dp->rotated()) { _rect.setRight(_rect.right() - _fontHeight); } else { _rect.setBottom(_rect.bottom() - _fontHeight); } } return _rect; } void RectDrawing::drawBack(QPainter *p, DrawParams *dp) { if (!dp) { dp = drawParams(); } if (_rect.width() <= 0 || _rect.height() <= 0) { return; } QRect r = _rect; QColor normal = dp->backColor(); if (dp->selected()) { normal = normal.light(); } bool isCurrent = dp->current(); if (dp->drawFrame() || isCurrent) { // 3D raised/sunken frame effect... QColor high = normal.light(); QColor low = normal.dark(); p->setPen(isCurrent ? low : high); p->drawLine(r.left(), r.top(), r.right(), r.top()); p->drawLine(r.left(), r.top(), r.left(), r.bottom()); p->setPen(isCurrent ? high : low); p->drawLine(r.right(), r.top(), r.right(), r.bottom()); p->drawLine(r.left(), r.bottom(), r.right(), r.bottom()); r.setRect(r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2); } if (r.width() <= 0 || r.height() <= 0) { return; } if (dp->shaded() && (r.width() > 0 && r.height() > 0)) { // adjustment for drawRect semantic in Qt4: decrement height/width r.setRect(r.x(), r.y(), r.width() - 1, r.height() - 1); // some shading bool goDark = qGray(normal.rgb()) > 128; int rBase, gBase, bBase; normal.getRgb(&rBase, &gBase, &bBase); p->setBrush(Qt::NoBrush); // shade parameters: int d = 7; float factor = 0.1, forth = 0.7, back1 = 0.9, toBack2 = .7, back2 = 0.97; // coefficient corrections because of rectangle size int s = r.width(); if (s > r.height()) { s = r.height(); } if (s < 100) { forth -= .3 * (100 - s) / 100; back1 -= .2 * (100 - s) / 100; back2 -= .02 * (100 - s) / 100; } // maximal color difference int rDiff = goDark ? -rBase / d : (255 - rBase) / d; int gDiff = goDark ? -gBase / d : (255 - gBase) / d; int bDiff = goDark ? -bBase / d : (255 - bBase) / d; QColor shadeColor; while (factor < .95 && (r.width() >= 0 && r.height() >= 0)) { shadeColor.setRgb((int)(rBase + factor * rDiff + .5), (int)(gBase + factor * gDiff + .5), (int)(bBase + factor * bDiff + .5)); p->setPen(shadeColor); p->drawRect(r); r.setRect(r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2); factor = 1.0 - ((1.0 - factor) * forth); } // and back (1st half) while (factor > toBack2 && (r.width() >= 0 && r.height() >= 0)) { shadeColor.setRgb((int)(rBase + factor * rDiff + .5), (int)(gBase + factor * gDiff + .5), (int)(bBase + factor * bDiff + .5)); p->setPen(shadeColor); p->drawRect(r); r.setRect(r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2); factor = 1.0 - ((1.0 - factor) / back1); } // and back (2nd half) while (factor > .01 && (r.width() >= 0 && r.height() >= 0)) { shadeColor.setRgb((int)(rBase + factor * rDiff + .5), (int)(gBase + factor * gDiff + .5), (int)(bBase + factor * bDiff + .5)); p->setPen(shadeColor); p->drawRect(r); r.setRect(r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2); factor = factor * back2; } normal = shadeColor; // for filling, width and height has to be incremented again r.setRect(r.x(), r.y(), r.width() + 1, r.height() + 1); } // fill inside p->fillRect(r, normal); } /* Helper for drawField * Find a line break position in a string, given a font and maximum width * * Returns the actually used width, and sets */ static int findBreak(int &breakPos, QString text, QFontMetrics *fm, int maxWidth) { int usedWidth; // does full text fit? breakPos = text.length(); usedWidth = fm->width(text); if (usedWidth < maxWidth) { return usedWidth; } // now lower breakPos until best position is found. // first by binary search, resulting in a position a little bit too large int bottomPos = 0; while (qAbs(maxWidth - usedWidth) > 3 * fm->maxWidth()) { int halfPos = (bottomPos + breakPos) / 2; int halfWidth = fm->width(text, halfPos); if (halfWidth < maxWidth) { bottomPos = halfPos; } else { breakPos = halfPos; usedWidth = halfWidth; } } // final position by taking break boundaries into account. // possible break boundaries are changing char categories but not middle of "Aa" QChar::Category lastCat, cat; int pos = breakPos; lastCat = text[pos - 1].category(); // at minimum 2 chars before break while (pos > 2) { pos--; cat = text[pos - 1].category(); if (cat == lastCat) { continue; } // "Aa" has not a possible break inbetween if ((cat == QChar::Letter_Uppercase) && (lastCat == QChar::Letter_Lowercase)) { lastCat = cat; continue; } lastCat = cat; breakPos = pos; usedWidth = fm->width(text, breakPos); if (usedWidth < maxWidth) { break; } } return usedWidth; } /* Helper for drawField * Find last line break position in a string from backwards, * given a font and maximum width * * Returns the actually used width, and sets */ static int findBreakBackwards(int &breakPos, QString text, QFontMetrics *fm, int maxWidth) { int usedWidth; // does full text fit? breakPos = 0; usedWidth = fm->width(text); if (usedWidth < maxWidth) { return usedWidth; } // now raise breakPos until best position is found. // first by binary search, resulting in a position a little bit too small int topPos = text.length(); while (qAbs(maxWidth - usedWidth) > 3 * fm->maxWidth()) { int halfPos = (breakPos + topPos) / 2; int halfWidth = fm->width(text.mid(halfPos)); if (halfWidth < maxWidth) { breakPos = halfPos; usedWidth = halfWidth; } else { topPos = halfPos; } } // final position by taking break boundaries into account. // possible break boundaries are changing char categories but not middle of "Aa" QChar::Category lastCat, cat; int pos = breakPos; lastCat = text[pos].category(); // at minimum 2 chars before break while (pos < text.length() - 2) { pos++; cat = text[pos].category(); if (cat == lastCat) { continue; } // "Aa" has not a possible break inbetween if ((lastCat == QChar::Letter_Uppercase) && (cat == QChar::Letter_Lowercase)) { lastCat = cat; continue; } lastCat = cat; breakPos = pos; usedWidth = fm->width(text.mid(breakPos)); if (usedWidth < maxWidth) { break; } } return usedWidth; } bool RectDrawing::drawField(QPainter *p, int f, DrawParams *dp) { if (!dp) { dp = drawParams(); } if (!_fm) { _fm = new QFontMetrics(dp->font()); _fontHeight = _fm->height(); } QRect r = _rect; int h = _fontHeight; bool rotate = dp->rotated(); int width = (rotate ? r.height() : r.width()) - 4; int height = (rotate ? r.width() : r.height()); int lines = height / h; // stop if there is no space available if (lines < 1) { return false; } // calculate free space in first line () int pos = dp->position(f); if (pos == DrawParams::Default) { switch (f % 4) { case 0: pos = DrawParams::TopLeft; break; case 1: pos = DrawParams::TopRight; break; case 2: pos = DrawParams::BottomRight; break; case 3: pos = DrawParams::BottomLeft; break; } } int unused = 0; bool isBottom = false; bool isCenter = false; bool isRight = false; - int *used = 0; + int *used = nullptr; switch (pos) { case DrawParams::TopLeft: used = &_usedTopLeft; if (_usedTopLeft == 0) { if (_usedTopCenter) { unused = (width - _usedTopCenter) / 2; } else { unused = width - _usedTopRight; } } break; case DrawParams::TopCenter: isCenter = true; used = &_usedTopCenter; if (_usedTopCenter == 0) { if (_usedTopLeft > _usedTopRight) { unused = width - 2 * _usedTopLeft; } else { unused = width - 2 * _usedTopRight; } } break; case DrawParams::TopRight: isRight = true; used = &_usedTopRight; if (_usedTopRight == 0) { if (_usedTopCenter) { unused = (width - _usedTopCenter) / 2; } else { unused = width - _usedTopLeft; } } break; case DrawParams::BottomLeft: isBottom = true; used = &_usedBottomLeft; if (_usedBottomLeft == 0) { if (_usedBottomCenter) { unused = (width - _usedBottomCenter) / 2; } else { unused = width - _usedBottomRight; } } break; case DrawParams::BottomCenter: isCenter = true; isBottom = true; used = &_usedBottomCenter; if (_usedBottomCenter == 0) { if (_usedBottomLeft > _usedBottomRight) { unused = width - 2 * _usedBottomLeft; } else { unused = width - 2 * _usedBottomRight; } } break; case DrawParams::BottomRight: isRight = true; isBottom = true; used = &_usedBottomRight; if (_usedBottomRight == 0) { if (_usedBottomCenter) { unused = (width - _usedBottomCenter) / 2; } else { unused = width - _usedBottomLeft; } } break; } if (isBottom) { if ((_usedTopLeft > 0) || (_usedTopCenter > 0) || (_usedTopRight > 0)) { lines--; } } else if (!isBottom) { if ((_usedBottomLeft > 0) || (_usedBottomCenter > 0) || (_usedBottomRight > 0)) { lines--; } } if (lines < 1) { return false; } int y = isBottom ? height - h : 0; if (unused < 0) { unused = 0; } if (unused == 0) { // no space available in last line at this position y = isBottom ? (y - h) : (y + h); lines--; if (lines < 1) { return false; } // new line: reset used space if (isBottom) { _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0; } else { _usedTopLeft = _usedTopCenter = _usedTopRight = 0; } unused = width; } // stop as soon as possible when there is no space for "..." static int dotW = 0; if (!dotW) { dotW = _fm->width("..."); } if (width < dotW) { return false; } // get text and pixmap now, only if we need to, because it is possible // that they are calculated on demand (and this can take some time) QString name = dp->text(f); if (name.isEmpty()) { return 0; } QPixmap pix = dp->pixmap(f); // check if pixmap can be drawn int pixW = pix.width(); int pixH = pix.height(); int pixY = 0; bool pixDrawn = true; if (pixW > 0) { pixW += 2; // X distance from pix if ((width < pixW + dotW) || (height < pixH)) { // do not draw pixW = 0; } else { pixDrawn = false; } } // width of text and pixmap to be drawn int w = pixW + _fm->width(name); // if we have limited space at 1st line: // use it only if whole name does fit in last line... if ((unused < width) && (w > unused)) { y = isBottom ? (y - h) : (y + h); lines--; if (lines < 1) { return false; } // new line: reset used space if (isBottom) { _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0; } else { _usedTopLeft = _usedTopCenter = _usedTopRight = 0; } } p->save(); p->setPen((qGray(dp->backColor().rgb()) > 100) ? Qt::black : Qt::white); p->setFont(dp->font()); if (rotate) { //p->translate(r.x()+2, r.y()+r.height()); p->translate(r.x(), r.y() + r.height() - 2); p->rotate(270); } else { p->translate(r.x() + 2, r.y()); } // adjust available lines according to maxLines int max = dp->maxLines(f); if ((max > 0) && (lines > max)) { lines = max; } /* loop over name parts to break up string depending on available width. * every char category change is supposed a possible break, * with the exception Uppercase=>Lowercase. * It is good enough for numbers, Symbols... * * If the text is to be written at the bottom, we start with the * end of the string (so everything is reverted) */ QString remaining; int origLines = lines; while (lines > 0) { // more than one line: search for line break if (w > width && lines > 1) { int breakPos; if (!isBottom) { w = pixW + findBreak(breakPos, name, _fm, width - pixW); remaining = name.mid(breakPos); // remove space on break point if (name[breakPos - 1].category() == QChar::Separator_Space) { name = name.left(breakPos - 1); } else { name = name.left(breakPos); } } else { // bottom w = pixW + findBreakBackwards(breakPos, name, _fm, width - pixW); remaining = name.left(breakPos); // remove space on break point if (name[breakPos].category() == QChar::Separator_Space) { name = name.mid(breakPos + 1); } else { name = name.mid(breakPos); } } } else { remaining.clear(); } /* truncate and add ... if needed */ if (w > width) { name = _fm->elidedText(name, Qt::ElideRight, width - pixW); w = _fm->width(name) + pixW; } int x = 0; if (isCenter) { x = (width - w) / 2; } else if (isRight) { x = width - w; } if (!pixDrawn) { pixY = y + (h - pixH) / 2; // default: center vertically if (pixH > h) { pixY = isBottom ? y - (pixH - h) : y; } p->drawPixmap(x, pixY, pix); // for distance to next text pixY = isBottom ? (pixY - h - 2) : (pixY + pixH + 2); pixDrawn = true; } p->drawText(x + pixW, y, width - pixW, h, Qt::AlignLeft, name); y = isBottom ? (y - h) : (y + h); lines--; if (remaining.isEmpty()) { break; } name = remaining; w = pixW + _fm->width(name); } // make sure the pix stays visible if (pixDrawn && (pixY > 0)) { if (isBottom && (pixY < y)) { y = pixY; } if (!isBottom && (pixY > y)) { y = pixY; } } if (origLines > lines) { // if only 1 line written, do not reset _used* vars if (lines - origLines > 1) { if (isBottom) { _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0; } else { _usedTopLeft = _usedTopCenter = _usedTopRight = 0; } } // take back one line y = isBottom ? (y + h) : (y - h); if (used) { *used = w; } } // update free space if (!isBottom) { if (rotate) { _rect.setRect(r.x() + y, r.y(), r.width() - y, r.height()); } else { _rect.setRect(r.x(), r.y() + y, r.width(), r.height() - y); } } else { if (rotate) { _rect.setRect(r.x(), r.y(), y + h, r.height()); } else { _rect.setRect(r.x(), r.y(), r.width(), y + h); } } p->restore(); return true; } diff --git a/src/svnfrontend/graphtree/graphtreelabel.cpp b/src/svnfrontend/graphtree/graphtreelabel.cpp index 84e4a88f..a8a29505 100644 --- a/src/svnfrontend/graphtree/graphtreelabel.cpp +++ b/src/svnfrontend/graphtree/graphtreelabel.cpp @@ -1,222 +1,222 @@ /*************************************************************************** * Copyright (C) 2006-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "graphtreelabel.h" #include "graphtree_defines.h" #include #include #include GraphTreeLabel::GraphTreeLabel(const QString &text, const QString &_nodename, const QRectF &r, QGraphicsItem *p) : QGraphicsRectItem(r, p), StoredDrawParams(), m_Nodename(_nodename), m_SourceNode() { m_Nodename = _nodename; setText(0, text); setPosition(0, DrawParams::TopCenter); drawFrame(true); } GraphTreeLabel::~GraphTreeLabel() { } const QString &GraphTreeLabel::nodename()const { return m_Nodename; } int GraphTreeLabel::type()const { return GRAPHTREE_LABEL; } void GraphTreeLabel::setBgColor(const QColor &c) { _backColor = c; } void GraphTreeLabel::paint(QPainter *p, const QStyleOptionGraphicsItem *option, QWidget *) { Q_UNUSED(option); QRect r = rect().toRect(); RectDrawing d(r); d.drawBack(p, this); d.drawField(p, 0, this); d.drawField(p, 1, this); } void GraphTreeLabel::setSelected(bool s) { QGraphicsItem::setSelected(s); StoredDrawParams::setSelected(s); update(); } const QString &GraphTreeLabel::source()const { return m_SourceNode; } void GraphTreeLabel::setSource(const QString &_s) { m_SourceNode = _s; } GraphEdge::GraphEdge(QGraphicsItem *c) : QGraphicsPathItem(c) { } GraphEdge::~GraphEdge() { } void GraphEdge::paint(QPainter *p, const QStyleOptionGraphicsItem *options, QWidget *) { Q_UNUSED(options); p->save(); p->setRenderHint(QPainter::Antialiasing); QPen pen = QPen(Qt::black); pen.setWidthF(1.0); p->setPen(pen); p->drawPath(path()); p->restore(); } const QPolygonF &GraphEdge::controlPoints()const { return _points; } void GraphEdge::setControlPoints(const QPolygonF &pa) { _points = pa; QPainterPath path; path.moveTo(pa[0]); for (int i = 1; i < pa.size(); i += 3) { path.cubicTo(pa[i], pa[(i + 1) % pa.size()], pa[(i + 2) % pa.size()]); } setPath(path); } int GraphEdge::type()const { return GRAPHTREE_LINE; } GraphEdgeArrow::GraphEdgeArrow(GraphEdge *_parent, QGraphicsItem *p) : QGraphicsPolygonItem(p), _edge(_parent) { } void GraphEdgeArrow::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) { p->save(); p->setRenderHint(QPainter::Antialiasing); p->setBrush(Qt::black); p->drawPolygon(polygon(), Qt::OddEvenFill); p->restore(); } int GraphEdgeArrow::type()const { return GRAPHTREE_ARROW; } GraphEdge *GraphEdgeArrow::edge() { return _edge; } /* taken from KCacheGrind project */ -QPixmap *GraphMark::_p = 0; +QPixmap *GraphMark::_p = nullptr; GraphMark::GraphMark(GraphTreeLabel *n, QGraphicsItem *p) : QGraphicsRectItem(p) { if (!_p) { int d = 5; float v1 = 130.0f, v2 = 10.0f, v = v1, f = 1.03f; // calculate pix size QRect r(0, 0, 30, 30); while (v > v2) { r.setRect(r.x() - d, r.y() - d, r.width() + 2 * d, r.height() + 2 * d); v /= f; } _p = new QPixmap(r.size()); _p->fill(Qt::white); QPainter p(_p); p.setPen(Qt::NoPen); r.translate(-r.x(), -r.y()); while (v < v1) { v *= f; p.setBrush(QColor(265 - (int)v, 265 - (int)v, 265 - (int)v)); p.drawRect(QRect(r.x(), r.y(), r.width(), d)); p.drawRect(QRect(r.x(), r.bottom() - d, r.width(), d)); p.drawRect(QRect(r.x(), r.y() + d, d, r.height() - 2 * d)); p.drawRect(QRect(r.right() - d, r.y() + d, d, r.height() - 2 * d)); r.setRect(r.x() + d, r.y() + d, r.width() - 2 * d, r.height() - 2 * d); } } setRect(QRectF(n->rect().center().x() - _p->width() / 2, n->rect().center().y() - _p->height() / 2, _p->width(), _p->height())); } GraphMark::~ GraphMark() { } bool GraphMark::hit(const QPoint &)const { return false; } int GraphMark::type()const { return GRAPHTREE_MARK; } void GraphMark::paint(QPainter *p, const QStyleOptionGraphicsItem *option, QWidget *) { if (option->levelOfDetail < .5) { QRadialGradient g(rect().center(), rect().width() / 3); g.setColorAt(0.0, Qt::gray); g.setColorAt(1.0, Qt::white); p->setBrush(QBrush(g)); p->setPen(Qt::NoPen); p->drawRect(rect()); return; } p->drawPixmap(int(rect().x()), int(rect().y()), *_p); } diff --git a/src/svnfrontend/graphtree/pannerview.cpp b/src/svnfrontend/graphtree/pannerview.cpp index 0b5dfad3..2878bfa7 100644 --- a/src/svnfrontend/graphtree/pannerview.cpp +++ b/src/svnfrontend/graphtree/pannerview.cpp @@ -1,150 +1,150 @@ /*************************************************************************** * Copyright (C) 2006-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "pannerview.h" #include "graphtree_defines.h" #include #include #include #include class GraphPanMark: public QGraphicsRectItem { public: - GraphPanMark(QGraphicsItem *p = 0); + GraphPanMark(QGraphicsItem *p = nullptr); virtual ~GraphPanMark(); virtual int type()const; virtual void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); }; GraphPanMark::GraphPanMark(QGraphicsItem *p) : QGraphicsRectItem(p) { setZValue(1.9); setPen(QPen(Qt::red)); QPen pe = pen(); pe.setWidthF(0.0); pe.setStyle(Qt::DashDotLine); setPen(pe); } GraphPanMark::~GraphPanMark() { } void GraphPanMark::paint(QPainter *p, const QStyleOptionGraphicsItem *option, QWidget *w) { if (option->levelOfDetail < .5) { QGraphicsRectItem::paint(p, option, w); } } int GraphPanMark::type()const { return GRAPHTREE_PANMARK; } PannerView::PannerView(QWidget *parent) : QGraphicsView(parent)// KDE4 check , /*Qt::WNoAutoErase |*/ Qt::WA_StaticContents/*WStaticContents*/ ) { - m_Mark = 0; + m_Mark = nullptr; m_Moving = false; viewport()->setFocusPolicy(Qt::NoFocus); setFocusPolicy(Qt::NoFocus); } PannerView::~PannerView() { if (scene() && m_Mark) { scene()->removeItem(m_Mark); delete m_Mark; } } void PannerView::setScene(QGraphicsScene *sc) { if (!sc) { if (scene()) { scene()->removeItem(m_Mark); } } else { if (!m_Mark) { m_Mark = new GraphPanMark; } sc->addItem(m_Mark); } QGraphicsView::setScene(sc); } void PannerView::setZoomRect(const QRectF &theValue) { m_ZoomRect = theValue; if (m_Mark) { m_Mark->setRect(m_ZoomRect); } } /*! \fn PannerView::contentsMouseMoveEvent(QMouseEvent* e) */ void PannerView::mouseMoveEvent(QMouseEvent *e) { if (m_Moving) { QPointF sPos = mapToScene(e->pos()); emit zoomRectMoved(sPos.x() - m_ZoomRect.center().x(), sPos.y() - m_ZoomRect.center().y()); m_LastPos = e->pos(); } } /*! \fn PannerView::contentsMousePressEvent(QMouseEvent* e) */ void PannerView::mousePressEvent(QMouseEvent *e) { if (m_ZoomRect.isValid()) { QPointF sPos = mapToScene(e->pos()); if (!m_ZoomRect.contains(sPos)) { emit zoomRectMoved(sPos.x() - m_ZoomRect.center().x(), sPos.y() - m_ZoomRect.center().y()); } m_Moving = true; m_LastPos = e->pos(); } } /*! \fn PannerView::contentsMouseReleaseEvent(QMouseEvent*) */ void PannerView::mouseReleaseEvent(QMouseEvent *) { m_Moving = false; emit zoomRectMoveFinished(); } /*! \fn PannerView::updateCurrentRect() */ void PannerView::updateCurrentRect() { if (m_ZoomRect.isValid()) { } } diff --git a/src/svnfrontend/graphtree/pannerview.h b/src/svnfrontend/graphtree/pannerview.h index 4389b8b2..3014ac95 100644 --- a/src/svnfrontend/graphtree/pannerview.h +++ b/src/svnfrontend/graphtree/pannerview.h @@ -1,59 +1,59 @@ /*************************************************************************** * Copyright (C) 2006-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef PANNERVIEW_H #define PANNERVIEW_H #include #include #include class GraphPanMark; /** @author Rajko Albrecht */ class PannerView : public QGraphicsView { Q_OBJECT public: - explicit PannerView(QWidget *parent = 0); + explicit PannerView(QWidget *parent = nullptr); virtual ~PannerView(); void setZoomRect(const QRectF &theValue); void updateCurrentRect(); virtual void setScene(QGraphicsScene *sc); signals: void zoomRectMoved(qreal dx, qreal dy); void zoomRectMoveFinished(); protected: virtual void mousePressEvent(QMouseEvent *); virtual void mouseMoveEvent(QMouseEvent *); virtual void mouseReleaseEvent(QMouseEvent *); protected: QRectF m_ZoomRect; bool m_Moving; QPoint m_LastPos; GraphPanMark *m_Mark; }; #endif diff --git a/src/svnfrontend/graphtree/revgraphview.cpp b/src/svnfrontend/graphtree/revgraphview.cpp index 82820223..01a80067 100644 --- a/src/svnfrontend/graphtree/revgraphview.cpp +++ b/src/svnfrontend/graphtree/revgraphview.cpp @@ -1,1006 +1,1006 @@ /*************************************************************************** * Copyright (C) 2006-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "revgraphview.h" #include "graphtreelabel.h" #include "pannerview.h" #include "graphtree_defines.h" #include "settings/kdesvnsettings.h" #include "../stopdlg.h" #include "svnqt/client.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define LABEL_WIDTH 160 #define LABEL_HEIGHT 90 RevGraphView::RevGraphView(const svn::ClientP &_client, QWidget *parent) : QGraphicsView(parent) - , m_Scene(0) - , m_Marker(0) + , m_Scene(nullptr) + , m_Marker(nullptr) , m_Client(_client) - , m_Selected(0) - , m_dotTmpFile(0) - , m_renderProcess(0) + , m_Selected(nullptr) + , m_dotTmpFile(nullptr) + , m_renderProcess(nullptr) , m_xMargin(0) , m_yMargin(0) , m_CompleteView(new PannerView(this)) , m_cvZoom(0) , m_LastAutoPosition(TopLeft) , m_isMoving(0) , m_noUpdateZoomerPos(false) { m_CompleteView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_CompleteView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_CompleteView->raise(); m_CompleteView->hide(); connect(m_CompleteView, SIGNAL(zoomRectMoved(qreal,qreal)), this, SLOT(zoomRectMoved(qreal,qreal))); connect(m_CompleteView, SIGNAL(zoomRectMoveFinished()), this, SLOT(zoomRectMoveFinished())); } RevGraphView::~RevGraphView() { - setScene(0); + setScene(nullptr); delete m_Scene; delete m_dotTmpFile; delete m_CompleteView; delete m_renderProcess; } void RevGraphView::showText(const QString &s) { clear(); m_Scene = new QGraphicsScene; m_Scene->addSimpleText(s); setScene(m_Scene); m_Scene->update(); m_CompleteView->hide(); } void RevGraphView::clear() { if (m_Selected) { m_Selected->setSelected(false); - m_Selected = 0; + m_Selected = nullptr; } if (m_Marker) { m_Marker->hide(); delete m_Marker; - m_Marker = 0; + m_Marker = nullptr; } - setScene(0); - m_CompleteView->setScene(0); + setScene(nullptr); + m_CompleteView->setScene(nullptr); delete m_Scene; - m_Scene = 0; + m_Scene = nullptr; } void RevGraphView::beginInsert() { viewport()->setUpdatesEnabled(false); } void RevGraphView::endInsert() { if (m_Scene) { /* _cvZoom = 0; updateSizes(); */ m_Scene->update(); } viewport()->setUpdatesEnabled(true); } void RevGraphView::readDotOutput() { if (!m_renderProcess) { return; } m_dotOutput += QString::fromLocal8Bit(m_renderProcess->readAllStandardOutput()); } void RevGraphView::dotExit(int exitcode, QProcess::ExitStatus exitStatus) { if (!m_renderProcess) { return; } if (exitStatus != QProcess::NormalExit || exitcode != 0) { QString error = i18n("Could not run process \"%1\".\n\nProcess stopped with message:\n%2", m_renderProcess->program().join(" "), QString::fromLocal8Bit(m_renderProcess->readAllStandardError())); showText(error); delete m_renderProcess; - m_renderProcess = 0; + m_renderProcess = nullptr; return; } // remove line breaks when lines to long QRegExp endslash("\\\\\\n"); m_dotOutput.remove(endslash); double scale = 1.0; double dotWidth = 1.0, dotHeight = 1.0; QTextStream dotStream(&m_dotOutput, QIODevice::ReadOnly); QString cmd; int lineno = 0; beginInsert(); clear(); /* mostly taken from kcachegrind */ double scaleX = scale * 60; double scaleY = scale * 70; QRectF startRect; while (!dotStream.atEnd()) { QString line = dotStream.readLine(); if (line.isNull()) { break; } lineno++; if (line.isEmpty()) { continue; } QTextStream lineStream(&line, QIODevice::ReadOnly); lineStream >> cmd; if (cmd == QLatin1String("stop")) { break; } if (cmd == QLatin1String("graph")) { lineStream >> scale >> dotWidth >> dotHeight; int w = qRound(scaleX * dotWidth); int h = qRound(scaleY * dotHeight); m_xMargin = 50; const QDesktopWidget *dw = QApplication::desktop(); if (w < dw->width()) { m_xMargin += (dw->width() - w) / 2; } m_yMargin = 50; if (h < dw->height()) { m_yMargin += (dw->height() - h) / 2; } m_Scene = new QGraphicsScene(0.0, 0.0, qreal(w + 2 * m_xMargin), qreal(h + 2 * m_yMargin)); m_Scene->setBackgroundBrush(Qt::white); continue; } if (m_dotTmpFile && (cmd != "node") && (cmd != "edge")) { qWarning() << "Ignoring unknown command '" << cmd << "' from dot (" << m_dotTmpFile->fileName() << ":" << lineno << ")" << endl; continue; } if (!m_Scene) { continue; } if (cmd == QLatin1String("node")) { QString nodeName, label; QString _x, _y, _w, _h; double x, y, width, height; lineStream >> nodeName >> _x >> _y >> _w >> _h; x = _x.toDouble(); y = _y.toDouble(); width = _w.toDouble(); height = _h.toDouble(); // better here 'cause dot may scramble utf8 labels so we regenerate it better // and do not read it in. label = getLabelstring(nodeName); double xx = (scaleX * x + m_xMargin); double yy = (scaleY * (dotHeight - y) + m_yMargin); double w = (scaleX * width); double h = (scaleY * height); QRectF r(xx - w / 2, yy - h / 2, w, h); GraphTreeLabel *t = new GraphTreeLabel(label, nodeName, r); m_Scene->addItem(t); if (isStart(nodeName)) { startRect = r; ensureVisible(startRect); } t->setBgColor(getBgColor(nodeName)); t->setZValue(1.0); t->show(); m_NodeList[nodeName] = t; t->setToolTip(toolTip(nodeName)); } else { QString node1Name, node2Name; QString _x, _y; double x, y; QPolygonF pa; int points, i; lineStream >> node1Name >> node2Name; lineStream >> points; pa.resize(points); for (i = 0; i < points; ++i) { if (lineStream.atEnd()) { break; } lineStream >> _x >> _y; x = _x.toDouble(); y = _y.toDouble(); double xx = (scaleX * x + m_xMargin); double yy = (scaleY * (dotHeight - y) + m_yMargin); #if 0 if (0) qDebug(" P %d: ( %f / %f ) => ( %d / %d)", i, x, y, xx, yy); #endif pa[i] = QPointF(xx, yy); } if (i < points) { qDebug("CallGraphView: Can't read %d spline points (%d)", points, lineno); continue; } GraphEdge *n = new GraphEdge(); QColor arrowColor = Qt::black; m_Scene->addItem(n); n->setPen(QPen(arrowColor, 1)); n->setControlPoints(pa); n->setZValue(0.5); n->show(); /* arrow dir * eg. it is vx and vy for computing, NO absolute points! */ QPointF arrowDir; int indexHead = -1; QMap::Iterator it; it = m_NodeList.find(node2Name); if (it != m_NodeList.end()) { it.value()->setSource(node1Name); } it = m_NodeList.find(node1Name); if (it != m_NodeList.end()) { GraphTreeLabel *tlab = it.value(); if (tlab) { QPointF toCenter = tlab->rect().center(); qreal dx0 = pa[0].x() - toCenter.x(); qreal dy0 = pa[0].y() - toCenter.y(); qreal dx1 = pa[points - 1].x() - toCenter.x(); qreal dy1 = pa[points - 1].y() - toCenter.y(); if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) { // start of spline is nearer to call target node indexHead = -1; while (arrowDir.isNull() && (indexHead < points - 2)) { indexHead++; arrowDir = pa[indexHead] - pa[indexHead + 1]; } } } } if (arrowDir.isNull()) { indexHead = points; // sometimes the last spline points from dot are the same... while (arrowDir.isNull() && (indexHead > 1)) { indexHead--; arrowDir = pa[indexHead] - pa[indexHead - 1]; } } if (!arrowDir.isNull()) { QPointF baseDir = arrowDir; arrowDir *= 10.0 / sqrt(double(arrowDir.x() * arrowDir.x() + arrowDir.y() * arrowDir.y())); baseDir /= (sqrt(baseDir.x() * baseDir.x() + baseDir.y() * baseDir.y())); QPointF t1(-baseDir.y() - baseDir.x(), baseDir.x() - baseDir.y()); QPointF t2(baseDir.y() - baseDir.x(), -baseDir.x() - baseDir.y()); QPolygonF a; t1 *= 3; t2 *= 3; a << pa[indexHead] + t1 << pa[indexHead] + arrowDir << pa[indexHead] + t2; - GraphEdgeArrow *aItem = new GraphEdgeArrow(n, 0); + GraphEdgeArrow *aItem = new GraphEdgeArrow(n, nullptr); m_Scene->addItem(aItem); aItem->setPolygon(a); aItem->setBrush(arrowColor); aItem->setZValue(1.5); aItem->show(); } } } if (!m_Scene) { QString s = i18n("Error running the graph layouting tool.\n"); s += i18n("Please check that 'dot' is installed (package GraphViz)."); showText(s); } else { setScene(m_Scene); m_CompleteView->setScene(m_Scene); if (startRect.isValid()) { ensureVisible(startRect); } } endInsert(); delete m_renderProcess; - m_renderProcess = 0; + m_renderProcess = nullptr; } bool RevGraphView::isStart(const QString &nodeName)const { bool res = false; trevTree::ConstIterator it; it = m_Tree.find(nodeName); if (it == m_Tree.end()) { return res; } switch (it.value().Action) { case 'A': res = true; break; } return res; } char RevGraphView::getAction(const QString &nodeName)const { trevTree::ConstIterator it; it = m_Tree.find(nodeName); if (it == m_Tree.end()) { return (char)0; } return it.value().Action; } QColor RevGraphView::getBgColor(const QString &nodeName)const { trevTree::ConstIterator it; it = m_Tree.find(nodeName); QColor res = Qt::white; if (it == m_Tree.end()) { return res; } switch (it.value().Action) { case 'D': res = Kdesvnsettings::tree_delete_color(); break; case 'R': case 'M': res = Kdesvnsettings::tree_modify_color(); break; case 'A': res = Kdesvnsettings::tree_add_color(); break; case 'C': case 1: res = Kdesvnsettings::tree_copy_color(); break; case 2: res = Kdesvnsettings::tree_rename_color(); break; default: res = Kdesvnsettings::tree_modify_color(); break; } return res; } QString RevGraphView::getLabelstring(const QString &nodeName) { QMap::ConstIterator nIt; nIt = m_LabelMap.constFind(nodeName); if (nIt != m_LabelMap.constEnd()) { return nIt.value(); } trevTree::ConstIterator it1; it1 = m_Tree.constFind(nodeName); if (it1 == m_Tree.constEnd()) { return QString(); } QString res; QString revstring = svn::Revision(it1.value().rev).toString(); switch (it1.value().Action) { case 'D': res = i18n("Deleted at revision %1", revstring); break; case 'A': res = i18n("Added at revision %1 as %2", revstring, it1.value().name); break; case 'C': case 1: res = i18n("Copied to %1 at revision %2", it1.value().name, revstring); break; case 2: res = i18n("Renamed to %1 at revision %2", it1.value().name, revstring); break; case 'M': res = i18n("Modified at revision %1", revstring); break; case 'R': res = i18n("Replaced at revision %1", revstring); break; default: res = i18n("Revision %1", revstring); break; } m_LabelMap[nodeName] = res; return m_LabelMap[nodeName]; } void RevGraphView::dumpRevtree() { if (m_dotTmpFile) { m_dotTmpFile->close(); delete m_dotTmpFile; } clear(); m_dotOutput.clear(); m_dotTmpFile = new QTemporaryFile(QLatin1String("XXXXXX.dot")); m_dotTmpFile->setAutoRemove(true); m_dotTmpFile->open(); if (!m_dotTmpFile->open()) { showText(i18n("Could not open temporary file %1 for writing.", m_dotTmpFile->fileName())); return; } QTextStream stream(m_dotTmpFile); QFont f = QFontDatabase::systemFont(QFontDatabase::FixedFont); QFontMetrics _fm(f); int _fontsize = _fm.height(); if (_fontsize < 0) { _fontsize = 10; } stream << "digraph \"callgraph\" {\n"; stream << " bgcolor=\"transparent\";\n"; int dir = Kdesvnsettings::tree_direction(); stream << QString(" rankdir=\""); switch (dir) { case 3: stream << "TB"; break; case 2: stream << "RL"; break; case 1: stream << "BT"; break; case 0: default: stream << "LR"; break; } stream << "\";\n"; //stream << QString(" overlap=false;\n splines=true;\n"); RevGraphView::trevTree::ConstIterator it1; for (it1 = m_Tree.constBegin(); it1 != m_Tree.constEnd(); ++it1) { stream << " " << it1.key() << "[ " << "shape=box, " << "label=\"" << "Zeile 1 geht ab Zeile 2 geht ab"/*getLabelstring(it1.key())*/ << "\"," << "fontsize=" << _fontsize << ",fontname=\"" << f.family() << "\"," << "];\n"; for (int j = 0; j < it1.value().targets.count(); ++j) { stream << " " << it1.key().toLatin1() << " " << "->" << " " << it1.value().targets[j].key << " [fontsize=" << _fontsize << ",fontname=\"" << f.family() << "\",style=\"solid\"];\n"; } } stream << "}\n" << flush; m_renderProcess = new KProcess(); m_renderProcess->setEnv("LANG", "C"); *m_renderProcess << "dot"; *m_renderProcess << m_dotTmpFile->fileName() << "-Tplain"; connect(m_renderProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(dotExit(int,QProcess::ExitStatus))); connect(m_renderProcess, SIGNAL(readyReadStandardOutput()), this, SLOT(readDotOutput())); m_renderProcess->setOutputChannelMode(KProcess::SeparateChannels); m_renderProcess->start(); } QString RevGraphView::toolTip(const QString &_nodename, bool full)const { QString res; trevTree::ConstIterator it = m_Tree.constFind(_nodename); if (it == m_Tree.constEnd()) { return res; } const QVector sp = it.value().Message.splitRef(QLatin1Char('\n')); QString sm; if (sp.isEmpty()) { sm = it.value().Message; } else { if (!full) { sm = sp[0].toString() + QLatin1String("..."); } else { for (int j = 0; j < sp.count(); ++j) { if (j > 0) { sm += QLatin1String("
"); } sm += sp[j].toString(); } } } if (!full && sm.length() > 50) { sm.truncate(47); sm += "..."; } static QLatin1String csep(""); static QLatin1String rend(""); static QLatin1String rstart(""); res = QLatin1String(""); if (!full) { res += QString(QLatin1String("%1")).arg(it.value().name); res += i18n("
Revision: %1
Author: %2
Date: %3
Log: %4", it.value().rev, it.value().Author, it.value().Date, sm); } else { res += QLatin1String("") + rstart + i18n("Revision%1%2%3", csep, it.value().rev, rend) + rstart + i18n("Author%1%2%3", csep, it.value().Author, rend) + rstart + i18n("Date%1%2%3", csep, it.value().Date, rend) + rstart + i18n("Log%1%2%3", csep, sm, rend) + QLatin1String("
") + it.value().name + QLatin1String("
"); } return res; } void RevGraphView::updateSizes(QSize s) { if (!m_Scene) { return; } if (s == QSize(0, 0)) { s = size(); } // the part of the canvas that should be visible qreal cWidth = m_Scene->width() - 2 * m_xMargin + 100; qreal cHeight = m_Scene->height() - 2 * m_yMargin + 100; // hide birds eye view if no overview needed if (((cWidth < s.width()) && cHeight < s.height()) || m_NodeList.isEmpty()) { m_CompleteView->hide(); return; } m_CompleteView->show(); // first, assume use of 1/3 of width/height (possible larger) double zoom = .33 * s.width() / cWidth; if (zoom * cHeight < .33 * s.height()) { zoom = .33 * s.height() / cHeight; } // fit to widget size if (cWidth * zoom > s.width()) { zoom = s.width() / (double)cWidth; } if (cHeight * zoom > s.height()) { zoom = s.height() / (double)cHeight; } // scale to never use full height/width zoom = zoom * 3 / 4; // at most a zoom of 1/3 if (zoom > .33) { zoom = .33; } if (zoom != m_cvZoom) { m_cvZoom = zoom; QMatrix wm; m_CompleteView->setMatrix(wm.scale(zoom, zoom)); // make it a little bigger to compensate for widget frame m_CompleteView->resize(int(cWidth * zoom) + 4, int(cHeight * zoom) + 4); // update ZoomRect in completeView scrollContentsBy(0, 0); } m_CompleteView->centerOn(m_Scene->width() / 2, m_Scene->height() / 2); updateZoomerPos(); } void RevGraphView::updateZoomerPos() { int cvW = m_CompleteView->width(); int cvH = m_CompleteView->height(); int x = width() - cvW - verticalScrollBar()->width() - 2; int y = height() - cvH - horizontalScrollBar()->height() - 2; QPoint oldZoomPos = m_CompleteView->pos(); QPoint newZoomPos = QPoint(0, 0); int tlCols = items(QRect(0, 0, cvW, cvH)).count(); int trCols = items(QRect(x, 0, cvW, cvH)).count(); int blCols = items(QRect(0, y, cvW, cvH)).count(); int brCols = items(QRect(x, y, cvW, cvH)).count(); int minCols = tlCols; ZoomPosition zp = m_LastAutoPosition; switch (zp) { case TopRight: minCols = trCols; break; case BottomLeft: minCols = blCols; break; case BottomRight: minCols = brCols; break; default: case TopLeft: minCols = tlCols; break; } if (minCols > tlCols) { minCols = tlCols; zp = TopLeft; } if (minCols > trCols) { minCols = trCols; zp = TopRight; } if (minCols > blCols) { minCols = blCols; zp = BottomLeft; } if (minCols > brCols) { minCols = brCols; zp = BottomRight; } m_LastAutoPosition = zp; switch (zp) { case TopRight: newZoomPos = QPoint(x, 0); break; case BottomLeft: newZoomPos = QPoint(0, y); break; case BottomRight: newZoomPos = QPoint(x, y); break; default: break; } if (newZoomPos != oldZoomPos) { m_CompleteView->move(newZoomPos); } } void RevGraphView::zoomRectMoved(qreal dx, qreal dy) { //if (leftMargin()>0) dx = 0; //if (topMargin()>0) dy = 0; m_noUpdateZoomerPos = true; QScrollBar *hBar = horizontalScrollBar(); QScrollBar *vBar = verticalScrollBar(); hBar->setValue(hBar->value() + int(dx)); vBar->setValue(vBar->value() + int(dy)); m_noUpdateZoomerPos = false; } void RevGraphView::zoomRectMoveFinished() { #if 0 if (_zoomPosition == Auto) #endif updateZoomerPos(); } void RevGraphView::resizeEvent(QResizeEvent *e) { QGraphicsView::resizeEvent(e); if (m_Scene) { updateSizes(e->size()); } } void RevGraphView::makeSelected(GraphTreeLabel *gtl) { if (m_Selected) { m_Selected->setSelected(false); } m_Selected = gtl; if (m_Marker) { m_Marker->hide(); delete m_Marker; - m_Marker = 0; + m_Marker = nullptr; } if (gtl) { m_Marker = new GraphMark(gtl); m_Scene->addItem(m_Marker); m_Marker->setPos(gtl->pos()); m_Marker->setZValue(-1); } m_Scene->update(); m_CompleteView->update(); } GraphTreeLabel *RevGraphView::firstLabelAt(const QPoint &pos)const { QList its = items(pos); for (QList::size_type i = 0; i < its.size(); ++i) { if (its[i]->type() == GRAPHTREE_LABEL) { return static_cast(its[i]); } } - return 0; + return nullptr; } void RevGraphView::mouseDoubleClickEvent(QMouseEvent *e) { setFocus(); if (e->button() == Qt::LeftButton) { GraphTreeLabel *i = firstLabelAt(e->pos()); - if (i == 0) { + if (i == nullptr) { return; } makeSelected(i); emit dispDetails(toolTip((i)->nodename(), true)); } } void RevGraphView::mousePressEvent(QMouseEvent *e) { setFocus(); if (e->button() == Qt::LeftButton) { m_isMoving = true; m_lastPos = e->pos(); } } void RevGraphView::mouseReleaseEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton && m_isMoving) { QPointF topLeft = mapToScene(QPoint(0, 0)); QPointF bottomRight = mapToScene(QPoint(width(), height())); QRectF z(topLeft, bottomRight); m_CompleteView->setZoomRect(z); m_isMoving = false; updateZoomerPos(); } } void RevGraphView::scrollContentsBy(int dx, int dy) { // call QGraphicsView implementation QGraphicsView::scrollContentsBy(dx, dy); QPointF topLeft = mapToScene(QPoint(0, 0)); QPointF bottomRight = mapToScene(QPoint(width(), height())); m_CompleteView->setZoomRect(QRectF(topLeft, bottomRight)); if (!m_noUpdateZoomerPos && !m_isMoving) { updateZoomerPos(); } } void RevGraphView::mouseMoveEvent(QMouseEvent *e) { if (m_isMoving) { QPoint delta = e->pos() - m_lastPos; QScrollBar *hBar = horizontalScrollBar(); QScrollBar *vBar = verticalScrollBar(); hBar->setValue(hBar->value() - delta.x()); vBar->setValue(vBar->value() - delta.y()); m_lastPos = e->pos(); } } void RevGraphView::setNewDirection(int dir) { if (dir < 0) { dir = 3; } else if (dir > 3) { dir = 0; } Kdesvnsettings::setTree_direction(dir); dumpRevtree(); } void RevGraphView::contextMenuEvent(QContextMenuEvent *e) { if (!m_Scene) { return; } GraphTreeLabel *i = firstLabelAt(e->pos()); QAction *ac; QMenu popup; if (i) { if (!i->source().isEmpty() && getAction(i->nodename()) != 'D') { popup.addAction(i18n("Diff to previous"))->setData(301); } if (m_Selected && m_Selected != i && getAction(m_Selected->nodename()) != 'D' && getAction(i->nodename()) != 'D') { popup.addAction(i18n("Diff to selected item"))->setData(302); } if (getAction(i->nodename()) != 'D') { popup.addAction(i18n("Cat this version"))->setData(303); } if (m_Selected == i) { popup.addAction(i18n("Unselect item"))->setData(401); } else { popup.addAction(i18n("Select item"))->setData(402); } popup.addSeparator(); popup.addAction(i18n("Display details"))->setData(403); popup.addSeparator(); } popup.addAction(i18n("Rotate counter-clockwise"))->setData(101); popup.addAction(i18n("Rotate clockwise"))->setData(102); popup.addSeparator(); ac = popup.addAction(i18n("Diff in revision tree is recursive")); ac->setData(202); ac->setCheckable(true); ac->setChecked(Kdesvnsettings::tree_diff_rec()); popup.addAction(i18n("Save tree as PNG"))->setData(201); ac = popup.exec(e->globalPos()); int r = 0; if (ac) { r = ac->data().toInt(); } switch (r) { case 101: { int dir = Kdesvnsettings::tree_direction(); setNewDirection(++dir); } break; case 102: { int dir = Kdesvnsettings::tree_direction(); setNewDirection(--dir); } break; case 201: { QString fn = QFileDialog::getSaveFileName(this, i18n("Save tree as PNG"), QString(), i18n("Image (*.png)")); if (!fn.isEmpty()) { if (m_Marker) { m_Marker->hide(); } if (m_Selected) { m_Selected->setSelected(false); } QRect r = m_Scene->sceneRect().toRect(); QPixmap pix(r.width(), r.height()); pix.fill(); QPainter p(&pix); m_Scene->render(&p); pix.save(fn, "PNG"); if (m_Marker) { m_Marker->show(); } if (m_Selected) { m_Selected->setSelected(true); m_Scene->update(); m_CompleteView->updateCurrentRect(); } } } break; case 202: Kdesvnsettings::setTree_diff_rec(!Kdesvnsettings::tree_diff_rec()); break; case 301: if (i && i->type() == GRAPHTREE_LABEL && !i->source().isEmpty()) { makeDiffPrev(i); } break; case 302: if (i && m_Selected) { makeDiff(i->nodename(), m_Selected->nodename()); } break; case 303: if (i) { makeCat(i); } break; case 401: - makeSelected(0); + makeSelected(nullptr); break; case 402: makeSelected(i); break; case 403: if (i) { emit dispDetails(toolTip(i->nodename(), true)); } break; default: break; } } void RevGraphView::makeCat(GraphTreeLabel *_l) { if (!_l) { return; } QString n1 = _l->nodename(); trevTree::ConstIterator it = m_Tree.constFind(n1); if (it == m_Tree.constEnd()) { return; } svn::Revision tr(it.value().rev); QString tp = m_basePath + it.value().name; emit makeCat(tr, tp, it.value().name, tr, QApplication::activeModalWidget()); } void RevGraphView::makeDiffPrev(GraphTreeLabel *_l) { if (!_l) { return; } QString n1, n2; n1 = _l->nodename(); n2 = _l->source(); makeDiff(n1, n2); } void RevGraphView::makeDiff(const QString &n1, const QString &n2) { if (n1.isEmpty() || n2.isEmpty()) { return; } trevTree::ConstIterator it; it = m_Tree.constFind(n2); if (it == m_Tree.constEnd()) { return; } svn::Revision sr(it.value().rev); QString sp = m_basePath + it.value().name; it = m_Tree.constFind(n1); if (it == m_Tree.constEnd()) { return; } svn::Revision tr(it.value().rev); QString tp = m_basePath + it.value().name; if (Kdesvnsettings::tree_diff_rec()) { emit makeRecDiff(sp, sr, tp, tr, QApplication::activeModalWidget()); } else { emit makeNorecDiff(sp, sr, tp, tr, QApplication::activeModalWidget()); } } void RevGraphView::setBasePath(const QString &_path) { m_basePath = _path; } void RevGraphView::slotClientException(const QString &what) { KMessageBox::sorry(QApplication::activeModalWidget(), what, i18n("SVN Error")); } diff --git a/src/svnfrontend/graphtree/revgraphview.h b/src/svnfrontend/graphtree/revgraphview.h index 4bb2b172..80b3730b 100644 --- a/src/svnfrontend/graphtree/revgraphview.h +++ b/src/svnfrontend/graphtree/revgraphview.h @@ -1,155 +1,155 @@ /*************************************************************************** * Copyright (C) 2006-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef REVGRAPHVIEW_H #define REVGRAPHVIEW_H #include #include #include #include #include #include #include namespace svn { class LogEntry; } class QTemporaryFile; class KProcess; class RevisionTree; class GraphTreeLabel; class GraphMark; class PannerView; class QGraphicsScene; class GraphTreeLabel; /** @author Rajko Albrecht */ class RevGraphView : public QGraphicsView { Q_OBJECT public: enum ZoomPosition { TopLeft, TopRight, BottomLeft, BottomRight, Auto }; /* avoid large copy operations */ friend class RevisionTree; - RevGraphView(const svn::ClientP &_client, QWidget *parent = 0); + RevGraphView(const svn::ClientP &_client, QWidget *parent = nullptr); virtual ~RevGraphView(); void showText(const QString &s); void clear(); void beginInsert(); void endInsert(); struct targetData { char Action; QString key; targetData(const QString &n, char _a) : Action(_a) , key(n) { } }; typedef QList tlist; struct keyData { QString name, Author, Date, Message; long rev; char Action; tlist targets; }; typedef QMap trevTree; QString toolTip(const QString &nodename, bool full = false)const; void setBasePath(const QString &); void dumpRevtree(); signals: void dispDetails(const QString &); void makeCat(const svn::Revision &, const QString &, const QString &, const svn::Revision &, QWidget *); void makeNorecDiff(const QString &, const svn::Revision &, const QString &, const svn::Revision &, QWidget *); void makeRecDiff(const QString &, const svn::Revision &, const QString &, const svn::Revision &, QWidget *); public slots: virtual void zoomRectMoved(qreal, qreal); virtual void zoomRectMoveFinished(); virtual void slotClientException(const QString &what); protected slots: virtual void readDotOutput(); virtual void dotExit(int, QProcess::ExitStatus); protected: QGraphicsScene *m_Scene; GraphMark *m_Marker; svn::ClientP m_Client; GraphTreeLabel *m_Selected; QTemporaryFile *m_dotTmpFile; QString m_dotOutput; KProcess *m_renderProcess; trevTree m_Tree; QColor getBgColor(const QString &nodeName)const; bool isStart(const QString &nodeName)const; char getAction(const QString &)const; QString getLabelstring(const QString &nodeName); QMap m_NodeList; QMap m_LabelMap; int m_xMargin, m_yMargin; PannerView *m_CompleteView; double m_cvZoom; ZoomPosition m_LastAutoPosition; virtual void resizeEvent(QResizeEvent *); virtual void mousePressEvent(QMouseEvent *e); virtual void mouseReleaseEvent(QMouseEvent *e); virtual void mouseMoveEvent(QMouseEvent *e); virtual void contextMenuEvent(QContextMenuEvent *e); virtual void mouseDoubleClickEvent(QMouseEvent *e); virtual void scrollContentsBy(int dx, int dy); GraphTreeLabel *firstLabelAt(const QPoint &pos)const; bool m_isMoving; QPoint m_lastPos; bool m_noUpdateZoomerPos; QString m_basePath; private: void updateSizes(QSize s = QSize(0, 0)); void updateZoomerPos(); void setNewDirection(int dir); void makeDiffPrev(GraphTreeLabel *); void makeDiff(const QString &, const QString &); void makeSelected(GraphTreeLabel *); void makeCat(GraphTreeLabel *_l); }; #endif diff --git a/src/svnfrontend/graphtree/revisiontree.cpp b/src/svnfrontend/graphtree/revisiontree.cpp index 839cd8f1..615a0901 100644 --- a/src/svnfrontend/graphtree/revisiontree.cpp +++ b/src/svnfrontend/graphtree/revisiontree.cpp @@ -1,523 +1,523 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "revisiontree.h" #include "../stopdlg.h" #include "svnqt/log_entry.h" #include "svnqt/cache/LogCache.h" #include "svnqt/cache/ReposLog.h" #include "svnqt/cache/ReposConfig.h" #include "svnqt/url.h" #include "svnqt/client_parameter.h" #include "revtreewidget.h" #include "revgraphview.h" #include "elogentry.h" #include "svnfrontend/fronthelpers/cursorstack.h" #include "settings/kdesvnsettings.h" #include #include #include #include #define INTERNALCOPY 1 #define INTERNALRENAME 2 class RtreeData { public: RtreeData(); virtual ~RtreeData(); QMap m_History; svn::LogEntriesMap m_OldHistory; long max_rev, min_rev; QProgressDialog *progress; QTime m_stopTick; QWidget *dlgParent; RevTreeWidget *m_TreeDisplay; svn::ClientP m_Client; QObject *m_Listener; bool getLogs(const QString &, const svn::Revision &startr, const svn::Revision &endr, const QString &origin); }; RtreeData::RtreeData() : max_rev(-1), min_rev(-1) { - progress = 0; - m_TreeDisplay = 0; - dlgParent = 0; - m_Listener = 0; + progress = nullptr; + m_TreeDisplay = nullptr; + dlgParent = nullptr; + m_Listener = nullptr; } RtreeData::~RtreeData() { delete progress; } bool RtreeData::getLogs(const QString &reposRoot, const svn::Revision &startr, const svn::Revision &endr, const QString &origin) { Q_UNUSED(origin); if (!m_Listener || !m_Client) { return false; } svn::LogParameter params; params.targets(reposRoot).revisionRange(endr, startr).peg(startr).limit(0).discoverChangedPathes(true).strictNodeHistory(false); const svn::StringArray ex(svn::cache::ReposConfig::self()->readEntry(reposRoot, "tree_exclude_list", QStringList())); try { CursorStack a(Qt::BusyCursor); StopDlg sdlg(m_Listener, dlgParent, i18nc("@title:window", "Logs"), i18n("Getting logs - hit Cancel for abort")); if (svn::Url::isLocal(reposRoot)) { m_Client->log(params.excludeList(ex), m_OldHistory); } else { svn::cache::ReposLog rl(m_Client, reposRoot); if (rl.isValid()) { rl.simpleLog(m_OldHistory, startr, endr, (!Kdesvnsettings::network_on() || !Kdesvnsettings::fill_cache_on_tree()), ex); } else if (Kdesvnsettings::network_on()) { m_Client->log(params.excludeList(ex), m_OldHistory); } else { - KMessageBox::error(0, i18n("Could not retrieve logs, reason:\n%1", i18n("No log cache possible due broken database and networking not allowed."))); + KMessageBox::error(nullptr, i18n("Could not retrieve logs, reason:\n%1", i18n("No log cache possible due broken database and networking not allowed."))); return false; } } } catch (const svn::Exception &ce) { - KMessageBox::error(0, i18n("Could not retrieve logs, reason:\n%1", ce.msg())); + KMessageBox::error(nullptr, i18n("Could not retrieve logs, reason:\n%1", ce.msg())); return false; } return true; } RevisionTree::RevisionTree(const svn::ClientP &aClient, QObject *aListener, const QString &reposRoot, const svn::Revision &startr, const svn::Revision &endr, const QString &origin, const svn::Revision &baserevision, QWidget *parent) : m_InitialRevsion(0), m_Path(origin), m_Valid(false) { m_Data = new RtreeData; m_Data->m_Client = aClient; m_Data->m_Listener = aListener; m_Data->dlgParent = parent; if (!m_Data->getLogs(reposRoot, startr, endr, origin)) { return; } long possible_rev = -1; m_Data->progress = new QProgressDialog(i18n("Scanning the logs for %1", origin), i18n("Cancel"), 0, m_Data->m_OldHistory.size(), parent); m_Data->progress->setWindowTitle(i18nc("@title:window", "Scanning logs")); m_Data->progress->setMinimumDuration(100); m_Data->progress->setAutoClose(false); m_Data->progress->setWindowModality(Qt::WindowModal); bool cancel = false; svn::LogEntriesMap::Iterator it; unsigned count = 0; for (it = m_Data->m_OldHistory.begin(); it != m_Data->m_OldHistory.end(); ++it) { m_Data->progress->setValue(count); QCoreApplication::processEvents(); if (m_Data->progress->wasCanceled()) { cancel = true; break; } if (it.key() > m_Data->max_rev) { m_Data->max_rev = it.key(); } if (it.key() < m_Data->min_rev || m_Data->min_rev == -1) { m_Data->min_rev = it.key(); } if (baserevision.kind() == svn_opt_revision_date) { if ((baserevision.date() <= it.value().date && possible_rev == -1) || possible_rev > it.key()) { possible_rev = it.key(); } } ++count; } if (baserevision.kind() == svn_opt_revision_head || baserevision.kind() == svn_opt_revision_working) { m_Baserevision = m_Data->max_rev; } else if (baserevision.kind() == svn_opt_revision_number) { m_Baserevision = baserevision.revnum(); } else if (baserevision.kind() == svn_opt_revision_date) { m_Baserevision = possible_rev; } else { m_Baserevision = m_Data->min_rev; } if (!cancel) { if (topDownScan()) { m_Data->progress->setAutoReset(true); m_Data->progress->setRange(0, 100); m_Data->m_stopTick.restart(); m_Data->m_TreeDisplay = new RevTreeWidget(m_Data->m_Client); if (bottomUpScan(m_InitialRevsion, 0, m_Path, 0)) { m_Valid = true; m_Data->m_TreeDisplay->setBasePath(reposRoot); m_Data->m_TreeDisplay->dumpRevtree(); } else { delete m_Data->m_TreeDisplay; - m_Data->m_TreeDisplay = 0; + m_Data->m_TreeDisplay = nullptr; } } } m_Data->progress->hide(); } RevisionTree::~RevisionTree() { delete m_Data; } bool RevisionTree::isDeleted(long revision, const QString &path) { for (long i = 0; i < m_Data->m_History[revision].changedPaths.count(); ++i) { if (isParent(m_Data->m_History[revision].changedPaths[i].path, path) && m_Data->m_History[revision].changedPaths[i].action == 'D') { return true; } } return false; } bool RevisionTree::topDownScan() { m_Data->progress->setRange(0, m_Data->max_rev - m_Data->min_rev); bool cancel = false; QString label; QString olabel = m_Data->progress->labelText(); for (long j = m_Data->max_rev; j >= m_Data->min_rev; --j) { m_Data->progress->setValue(m_Data->max_rev - j); QCoreApplication::processEvents(); if (m_Data->progress->wasCanceled()) { cancel = true; break; } for (long i = 0; i < m_Data->m_OldHistory[j].changedPaths.count(); ++i) { if (i > 0 && i % 100 == 0) { if (m_Data->progress->wasCanceled()) { cancel = true; break; } label = i18n("%1
Check change entry %2 of %3", olabel, i, m_Data->m_OldHistory[j].changedPaths.count()); m_Data->progress->setLabelText(label); QCoreApplication::processEvents(); } /* find min revision of item */ if (m_Data->m_OldHistory[j].changedPaths[i].action == 'A' && isParent(m_Data->m_OldHistory[j].changedPaths[i].path, m_Path)) { if (!m_Data->m_OldHistory[j].changedPaths[i].copyFromPath.isEmpty()) { if (m_InitialRevsion < m_Data->m_OldHistory[j].revision) { QString r = m_Path.mid(m_Data->m_OldHistory[j].changedPaths[i].path.length()); m_Path = m_Data->m_OldHistory[j].changedPaths[i].copyFromPath; m_Path += r; } } else if (m_Data->m_OldHistory[j].changedPaths[i].path == m_Path && m_Data->m_OldHistory[j].changedPaths[i].copyToPath.isEmpty()) { // here it is added m_InitialRevsion = m_Data->m_OldHistory[j].revision; } } } } if (cancel == true) { return false; } m_Data->progress->setLabelText(olabel); /* find forward references and filter them out */ for (long j = m_Data->max_rev; j >= m_Data->min_rev; --j) { m_Data->progress->setValue(m_Data->max_rev - j); QCoreApplication::processEvents(); if (m_Data->progress->wasCanceled()) { cancel = true; break; } for (long i = 0; i < m_Data->m_OldHistory[j].changedPaths.count(); ++i) { if (i > 0 && i % 100 == 0) { if (m_Data->progress->wasCanceled()) { cancel = true; break; } label = i18n("%1
Check change entry %2 of %3", olabel, i, m_Data->m_OldHistory[j].changedPaths.count()); m_Data->progress->setLabelText(label); QCoreApplication::processEvents(); } if (!m_Data->m_OldHistory[j].changedPaths[i].copyFromPath.isEmpty()) { long r = m_Data->m_OldHistory[j].changedPaths[i].copyFromRevision; QString sourcepath = m_Data->m_OldHistory[j].changedPaths[i].copyFromPath; char a = m_Data->m_OldHistory[j].changedPaths[i].action; if (m_Data->m_OldHistory[j].changedPaths[i].path.isEmpty()) { continue; } if (a == 'R') { m_Data->m_OldHistory[j].changedPaths[i].action = 0; } else if (a == 'A') { a = INTERNALCOPY; for (long z = 0; z < m_Data->m_OldHistory[j].changedPaths.count(); ++z) { if (m_Data->m_OldHistory[j].changedPaths[z].action == 'D' && isParent(m_Data->m_OldHistory[j].changedPaths[z].path, sourcepath)) { a = INTERNALRENAME; m_Data->m_OldHistory[j].changedPaths[z].action = 0; break; } } m_Data->m_History[r].addCopyTo(sourcepath, m_Data->m_OldHistory[j].changedPaths[i].path, j, a, r); m_Data->m_OldHistory[j].changedPaths[i].action = 0; } } } } if (cancel == true) { return false; } m_Data->progress->setLabelText(olabel); for (long j = m_Data->max_rev; j >= m_Data->min_rev; --j) { m_Data->progress->setValue(m_Data->max_rev - j); QCoreApplication::processEvents(); if (m_Data->progress->wasCanceled()) { cancel = true; break; } for (long i = 0; i < m_Data->m_OldHistory[j].changedPaths.count(); ++i) { if (m_Data->m_OldHistory[j].changedPaths[i].action == 0) { continue; } if (i > 0 && i % 100 == 0) { if (m_Data->progress->wasCanceled()) { cancel = true; break; } label = i18n("%1
Check change entry %2 of %3", olabel, i, m_Data->m_OldHistory[j].changedPaths.count()); m_Data->progress->setLabelText(label); QCoreApplication::processEvents(); } m_Data->m_History[j].addCopyTo(m_Data->m_OldHistory[j].changedPaths[i].path, QString(), -1, m_Data->m_OldHistory[j].changedPaths[i].action); } m_Data->m_History[j].author = m_Data->m_OldHistory[j].author; m_Data->m_History[j].date = m_Data->m_OldHistory[j].date; m_Data->m_History[j].revision = m_Data->m_OldHistory[j].revision; m_Data->m_History[j].message = m_Data->m_OldHistory[j].message; } return !cancel; } bool RevisionTree::isParent(const QString &_par, const QString &tar) { if (_par == tar) { return true; } QString par = _par.endsWith(QLatin1Char('/')) ? _par : _par + QLatin1Char('/'); return tar.startsWith(par); } bool RevisionTree::isValid()const { return m_Valid; } static QString uniqueNodeName(long rev, const QString &path) { QString res = QString::fromUtf8(path.toLocal8Bit().toBase64()); res.replace(QLatin1Char('\"'), QLatin1String("_quot_")); res.replace(QLatin1Char(' '), QLatin1String("_space_")); QString n; n.sprintf("%05ld", rev); return QLatin1Char('\"') + n + QLatin1Char('_') + res + QLatin1Char('\"'); } bool RevisionTree::bottomUpScan(long startrev, unsigned recurse, const QString &_path, long _last) { #define REVENTRY m_Data->m_History[j] #define FORWARDENTRY m_Data->m_History[j].changedPaths[i] QString path = _path; long lastrev = _last; #ifdef DEBUG_PARSE qCDebug(KDESVN_LOG) << "Searching for " << path << " at revision " << startrev << " recursion " << recurse << endl; #endif bool cancel = false; for (long j = startrev; j <= m_Data->max_rev; ++j) { if (m_Data->m_stopTick.elapsed() > 500) { m_Data->progress->setValue(m_Data->progress->value() + 1); QCoreApplication::processEvents(); m_Data->m_stopTick.restart(); } if (m_Data->progress->wasCanceled()) { cancel = true; break; } for (long i = 0; i < REVENTRY.changedPaths.count(); ++i) { if (!isParent(FORWARDENTRY.path, path)) { continue; } QString n1, n2; if (isParent(FORWARDENTRY.path, path)) { bool get_out = false; if (FORWARDENTRY.path != path) { #ifdef DEBUG_PARSE qCDebug(KDESVN_LOG) << "Parent rename? " << FORWARDENTRY.path << " -> " << FORWARDENTRY.copyToPath << " -> " << FORWARDENTRY.copyFromPath << endl; #endif } if (FORWARDENTRY.action == INTERNALCOPY || FORWARDENTRY.action == INTERNALRENAME) { bool ren = FORWARDENTRY.action == INTERNALRENAME; QString tmpPath = path; QString recPath; if (FORWARDENTRY.copyToPath.length() == 0) { continue; } QString r = path.mid(FORWARDENTRY.path.length()); recPath = FORWARDENTRY.copyToPath; recPath += r; n1 = uniqueNodeName(lastrev, tmpPath); n2 = uniqueNodeName(FORWARDENTRY.copyToRevision, recPath); if (lastrev > 0) { m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n1].targets.append(RevGraphView::targetData(n2, FORWARDENTRY.action)); } m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].name = recPath; m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].rev = FORWARDENTRY.copyToRevision; m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].Action = FORWARDENTRY.action; m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].Author = m_Data->m_History[FORWARDENTRY.copyToRevision].author; m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].Message = m_Data->m_History[FORWARDENTRY.copyToRevision].message; m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].Date = svn::DateTime(m_Data->m_History[FORWARDENTRY.copyToRevision].date).toString(); if (ren) { lastrev = FORWARDENTRY.copyToRevision; /* skip items between */ #ifdef DEBUG_PARSE qCDebug(KDESVN_LOG) << "Renamed to " << recPath << " at revision " << FORWARDENTRY.copyToRevision << endl; #endif j = lastrev; path = recPath; } else { #ifdef DEBUG_PARSE qCDebug(KDESVN_LOG) << "Copy to " << recPath << endl; #endif if (!bottomUpScan(FORWARDENTRY.copyToRevision, recurse + 1, recPath, FORWARDENTRY.copyToRevision)) { return false; } } } else if (FORWARDENTRY.path == path) { switch (FORWARDENTRY.action) { case 'A': #ifdef DEBUG_PARSE qCDebug(KDESVN_LOG) << "Inserting adding base item" << endl; #endif n1 = uniqueNodeName(j, FORWARDENTRY.path); m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n1].Action = FORWARDENTRY.action; fillItem(j, i, n1, path); lastrev = j; break; case 'M': case 'R': #ifdef DEBUG_PARSE qCDebug(KDESVN_LOG) << "Item modified at revision " << j << " recurse " << recurse << endl; #endif n1 = uniqueNodeName(j, FORWARDENTRY.path); n2 = uniqueNodeName(lastrev, FORWARDENTRY.path); if (lastrev > 0) { m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].targets.append(RevGraphView::targetData(n1, FORWARDENTRY.action)); } fillItem(j, i, n1, path); /* modify of same item (in same recurse) should be only once at a revision * so check if lastrev==j must not be done but will cost cpu ticks so I always * set trev and lastrev. */ lastrev = j; break; case 'D': #ifdef DEBUG_PARSE qCDebug(KDESVN_LOG) << "(Sloppy match) Item deleted at revision " << j << " recurse " << recurse << endl; #endif n1 = uniqueNodeName(j, path); n2 = uniqueNodeName(lastrev, path); if (n1 == n2) { /* cvs import - copy and deletion at same revision. * CVS sucks. */ n1 = uniqueNodeName(j, "D_" + path); } if (lastrev > 0) { m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].targets.append(RevGraphView::targetData(n1, FORWARDENTRY.action)); } fillItem(j, i, n1, path); lastrev = j; get_out = true; break; default: break; } } else { switch (FORWARDENTRY.action) { case 'D': #ifdef DEBUG_PARSE qCDebug(KDESVN_LOG) << "(Exact match) Item deleted at revision " << j << " recurse " << recurse << endl; #endif n1 = uniqueNodeName(j, path); n2 = uniqueNodeName(lastrev, path); if (n1 == n2) { /* cvs import - copy and deletion at same revision. * CVS sucks. */ n1 = uniqueNodeName(j, "D_" + path); } if (lastrev > 0) { m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[n2].targets.append(RevGraphView::targetData(n1, FORWARDENTRY.action)); } fillItem(j, i, n1, path); lastrev = j; get_out = true; break; default: break; } } if (get_out) { return true; } } } } return !cancel; } QWidget *RevisionTree::getView() { return m_Data->m_TreeDisplay; } void RevisionTree::fillItem(long rev, int pathIndex, const QString &nodeName, const QString &path) { m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].name = path; m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].rev = rev; if (pathIndex >= 0) { m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Action = m_Data->m_History[rev].changedPaths[pathIndex].action; m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Author = m_Data->m_History[rev].author; m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Message = m_Data->m_History[rev].message; m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Date = svn::DateTime(m_Data->m_History[rev].date).toString(); } else { m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Action = 0; m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Author.clear(); m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Message.clear(); m_Data->m_TreeDisplay->m_RevGraphView->m_Tree[nodeName].Date = svn::DateTime(0).toString(); } } diff --git a/src/svnfrontend/graphtree/revtreewidget.h b/src/svnfrontend/graphtree/revtreewidget.h index c3cea551..30bc4b13 100644 --- a/src/svnfrontend/graphtree/revtreewidget.h +++ b/src/svnfrontend/graphtree/revtreewidget.h @@ -1,65 +1,65 @@ /*************************************************************************** * Copyright (C) 2006-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef REVTREEWIDGET_H #define REVTREEWIDGET_H #include #include #include class QVBoxLayout; class RevGraphView; class QSplitter; class QTextBrowser; namespace svn { class LogEntry; } class RevTreeWidget : public QWidget { Q_OBJECT public: - RevTreeWidget(const svn::ClientP &cl, QWidget *parent = 0); + RevTreeWidget(const svn::ClientP &cl, QWidget *parent = nullptr); ~RevTreeWidget(); QSplitter *m_Splitter; RevGraphView *m_RevGraphView; void setBasePath(const QString &); void dumpRevtree(); protected: QVBoxLayout *RevTreeWidgetLayout; QTextBrowser *m_Detailstext; signals: void makeCat(const svn::Revision &, const QString &, const QString &, const svn::Revision &, QWidget *); void makeNorecDiff(const QString &, const svn::Revision &, const QString &, const svn::Revision &, QWidget *); void makeRecDiff(const QString &, const svn::Revision &, const QString &, const svn::Revision &, QWidget *); protected slots: virtual void setDetailText(const QString &); }; #endif // REVTREEWIDGET_H diff --git a/src/svnfrontend/hotcopydlg_impl.h b/src/svnfrontend/hotcopydlg_impl.h index 6e61b02d..7b7af3b3 100644 --- a/src/svnfrontend/hotcopydlg_impl.h +++ b/src/svnfrontend/hotcopydlg_impl.h @@ -1,41 +1,41 @@ /*************************************************************************** * Copyright (C) 2006-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef HOTCOPYDLG_IMPL_H #define HOTCOPYDLG_IMPL_H #include "ui_hotcopydlg.h" #include #include class HotcopyDlg_impl: public QWidget, public Ui::HotcopyDlg { Q_OBJECT public: - explicit HotcopyDlg_impl(QWidget *parent = 0); + explicit HotcopyDlg_impl(QWidget *parent = nullptr); virtual ~HotcopyDlg_impl(); QString srcPath()const; QString destPath()const; bool cleanLogs()const; }; #endif diff --git a/src/svnfrontend/importdir_logmsg.cpp b/src/svnfrontend/importdir_logmsg.cpp index 74a08d1f..b9f1ab4a 100644 --- a/src/svnfrontend/importdir_logmsg.cpp +++ b/src/svnfrontend/importdir_logmsg.cpp @@ -1,81 +1,81 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "importdir_logmsg.h" #include "svnqt/version_check.h" #include #include Importdir_logmsg::Importdir_logmsg(QWidget *parent) : Commitmsg_impl(parent) { m_createDirBox = new QCheckBox(this); hideKeepsLock(true); createDirboxDir(); addItemWidget(m_createDirBox); m_createDirBox->setChecked(true); QHBoxLayout *tmpLayout = new QHBoxLayout(); m_noIgnore = new QCheckBox(this); m_noIgnore->setText(i18n("No ignore")); m_noIgnore->setToolTip(i18n("If set, add files or directories that match ignore patterns.")); tmpLayout->addWidget(m_noIgnore); //LogmessageDataLayout->addWidget(m_createDirBox); if (svn::Version::version_major() > 1 || svn::Version::version_minor() > 4) { m_ignoreUnknownNodes = new QCheckBox(this); m_ignoreUnknownNodes->setText(i18n("Ignore unknown node types")); m_ignoreUnknownNodes->setToolTip(i18n("Should files with unknown node types be ignored")); m_ignoreUnknownNodes->setWhatsThis(i18n("Ignore files of which the node type is unknown, such as device files and pipes.")); tmpLayout->addWidget(m_ignoreUnknownNodes); //addItemWidget(m_ignoreUnknownNodes); } else { - m_ignoreUnknownNodes = 0; + m_ignoreUnknownNodes = nullptr; } QSpacerItem *m_leftspacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); tmpLayout->addItem(m_leftspacer); if (layout()) { layout()->addItem(tmpLayout); } } Importdir_logmsg::~Importdir_logmsg() { } bool Importdir_logmsg::noIgnore() { return m_noIgnore->isChecked(); } bool Importdir_logmsg::ignoreUnknownNodes() { return m_ignoreUnknownNodes ? m_ignoreUnknownNodes->isChecked() : false; } bool Importdir_logmsg::createDir() { return m_createDirBox->isChecked(); } void Importdir_logmsg::createDirboxDir(const QString &which) { m_createDirBox->setText(i18n("Create subdirectory %1 on import", (which.isEmpty() ? i18n("(Last part)") : which))); } diff --git a/src/svnfrontend/importdir_logmsg.h b/src/svnfrontend/importdir_logmsg.h index 30e38f33..84944592 100644 --- a/src/svnfrontend/importdir_logmsg.h +++ b/src/svnfrontend/importdir_logmsg.h @@ -1,48 +1,48 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef IMPORTDIR_LOGMSG_H #define IMPORTDIR_LOGMSG_H #include "ksvnwidgets/commitmsg_impl.h" class QCheckBox; /** @author Rajko Albrecht */ class Importdir_logmsg : public Commitmsg_impl { Q_OBJECT public: - explicit Importdir_logmsg(QWidget *parent = 0); + explicit Importdir_logmsg(QWidget *parent = nullptr); virtual ~Importdir_logmsg(); bool createDir(); bool ignoreUnknownNodes(); bool noIgnore(); void createDirboxDir(const QString &which = QString()); protected: QCheckBox *m_createDirBox; QCheckBox *m_ignoreUnknownNodes; QCheckBox *m_noIgnore; }; #endif diff --git a/src/svnfrontend/loaddmpdlg_impl.h b/src/svnfrontend/loaddmpdlg_impl.h index bb75279f..faa5c88b 100644 --- a/src/svnfrontend/loaddmpdlg_impl.h +++ b/src/svnfrontend/loaddmpdlg_impl.h @@ -1,42 +1,42 @@ /*************************************************************************** * Copyright (C) 2006-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef LOADDMPDLG_IMPL_H #define LOADDMPDLG_IMPL_H #include "ui_loaddmpdlg.h" class LoadDmpDlg_impl: public QWidget, public Ui::LoadDmpDlg { Q_OBJECT public: - explicit LoadDmpDlg_impl(QWidget *parent = 0); + explicit LoadDmpDlg_impl(QWidget *parent = nullptr); virtual ~LoadDmpDlg_impl(); bool usePost()const; bool usePre()const; bool validateProps()const; int uuidAction()const; QUrl dumpFile()const; QString repository()const; QString parentPath()const; public slots: }; #endif diff --git a/src/svnfrontend/maintreewidget.cpp b/src/svnfrontend/maintreewidget.cpp index 7b9912b9..129aab63 100644 --- a/src/svnfrontend/maintreewidget.cpp +++ b/src/svnfrontend/maintreewidget.cpp @@ -1,2368 +1,2368 @@ /*************************************************************************** * Copyright (C) 2008 by Rajko Albrecht ral@alwins-world.de * * http://kdesvn.alwins-world.de/ * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "maintreewidget.h" #include "models/svnitemmodel.h" #include "models/svnitemnode.h" #include "models/svnsortfilter.h" #include "models/svndirsortfilter.h" #include "database/dbsettings.h" #include "cursorstack.h" #include "svnactions.h" #include "copymoveview_impl.h" #include "mergedlg_impl.h" #include "checkoutinfo_impl.h" #include "importdir_logmsg.h" #include "settings/kdesvnsettings.h" #include "helpers/sshagent.h" #include "svnqt/targets.h" #include "svnqt/url.h" #include "fronthelpers/rangeinput_impl.h" #include "fronthelpers/widgetblockstack.h" #include "fronthelpers/fronthelpers.h" #include "ksvnwidgets/commitmsg_impl.h" #include "ksvnwidgets/deleteform.h" #include "helpers/kdesvn_debug.h" #include "opencontextmenu.h" #include "EditIgnorePattern.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class MainTreeWidgetData { public: MainTreeWidgetData() { - m_Collection = 0; - m_Model = 0; - m_SortModel = 0; - m_DirSortModel = 0; + m_Collection = nullptr; + m_Model = nullptr; + m_SortModel = nullptr; + m_DirSortModel = nullptr; m_remoteRevision = svn::Revision::UNDEFINED; } ~MainTreeWidgetData() { delete m_Model; delete m_SortModel; delete m_DirSortModel; } QModelIndex srcInd(const QModelIndex &ind) { return m_SortModel->mapToSource(ind); } QModelIndex srcDirInd(const QModelIndex &ind) { return m_DirSortModel->mapToSource(ind); } SvnItemModelNode *sourceNode(const QModelIndex &index, bool left) { if (!index.isValid()) { - return 0; + return nullptr; } QModelIndex ind = left ? m_DirSortModel->mapToSource(index) : m_SortModel->mapToSource(index); if (ind.isValid()) { return static_cast(ind.internalPointer()); } - return 0; + return nullptr; } KActionCollection *m_Collection; SvnItemModel *m_Model; SvnSortFilterProxy *m_SortModel; SvnDirSortFilterProxy *m_DirSortModel; svn::Revision m_remoteRevision; QString merge_Target, merge_Src2, merge_Src1; QTimer m_TimeModified, m_TimeUpdates, m_resizeColumnsTimer; }; MainTreeWidget::MainTreeWidget(KActionCollection *aCollection, QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f), m_Data(new MainTreeWidgetData) { setupUi(this); setFocusPolicy(Qt::StrongFocus); m_TreeView->setFocusPolicy(Qt::StrongFocus); m_Data->m_Collection = aCollection; m_Data->m_SortModel = new SvnSortFilterProxy(); m_Data->m_SortModel->setDynamicSortFilter(true); m_Data->m_SortModel->setSortRole(SORT_ROLE); m_Data->m_SortModel->setSortCaseSensitivity(Kdesvnsettings::case_sensitive_sort() ? Qt::CaseSensitive : Qt::CaseInsensitive); m_Data->m_SortModel->sort(0); m_TreeView->setModel(m_Data->m_SortModel); m_TreeView->sortByColumn(0, Qt::AscendingOrder); m_Data->m_Model = new SvnItemModel(this); m_Data->m_SortModel->setSourceModel(m_Data->m_Model); m_Data->m_DirSortModel = new SvnDirSortFilterProxy(); m_Data->m_DirSortModel->setDynamicSortFilter(true); m_Data->m_DirSortModel->setSortRole(SORT_ROLE); m_Data->m_DirSortModel->setSortCaseSensitivity(Kdesvnsettings::case_sensitive_sort() ? Qt::CaseSensitive : Qt::CaseInsensitive); m_DirTreeView->setModel(m_Data->m_DirSortModel); m_Data->m_DirSortModel->setSourceModel(m_Data->m_Model); connect(m_TreeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection))); connect(m_DirTreeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(slotDirSelectionChanged(QItemSelection,QItemSelection))); connect(m_Data->m_Model->svnWrapper(), SIGNAL(clientException(QString)), this, SLOT(slotClientException(QString))); connect(m_Data->m_Model, SIGNAL(clientException(QString)), this, SLOT(slotClientException(QString))); connect(m_Data->m_Model->svnWrapper(), SIGNAL(sendNotify(QString)), this, SLOT(slotNotifyMessage(QString))); connect(m_Data->m_Model->svnWrapper(), SIGNAL(reinitItem(SvnItem*)), this, SLOT(slotReinitItem(SvnItem*))); connect(m_Data->m_Model->svnWrapper(), SIGNAL(sigRefreshAll()), this, SLOT(refreshCurrentTree())); connect(m_Data->m_Model->svnWrapper(), SIGNAL(sigRefreshCurrent(SvnItem*)), this, SLOT(refreshCurrent(SvnItem*))); connect(m_Data->m_Model->svnWrapper(), SIGNAL(sigRefreshIcons()), this, SLOT(slotRescanIcons())); connect(m_Data->m_Model->svnWrapper(), SIGNAL(sigGotourl(QUrl)), this, SLOT(_openUrl(QUrl))); connect(m_Data->m_Model->svnWrapper(), SIGNAL(sigCacheStatus(qlonglong,qlonglong)), this, SIGNAL(sigCacheStatus(qlonglong,qlonglong))); connect(m_Data->m_Model->svnWrapper(), SIGNAL(sigThreadsChanged()), this, SLOT(enableActions())); connect(m_Data->m_Model->svnWrapper(), SIGNAL(sigCacheDataChanged()), this, SLOT(slotCacheDataChanged())); connect(m_Data->m_Model->svnWrapper(), SIGNAL(sigExtraStatusMessage(QString)), this, SIGNAL(sigExtraStatusMessage(QString))); connect(m_Data->m_Model, SIGNAL(urlDropped(QList,Qt::DropAction,QModelIndex,bool)), this, SLOT(slotUrlDropped(QList,Qt::DropAction,QModelIndex,bool))); connect(m_Data->m_Model, SIGNAL(itemsFetched(QModelIndex)), this, SLOT(slotItemsInserted(QModelIndex))); m_TreeView->sortByColumn(0, Qt::AscendingOrder); m_DirTreeView->sortByColumn(0, Qt::AscendingOrder); checkUseNavigation(true); setupActions(); m_Data->m_TimeModified.setParent(this); connect(&(m_Data->m_TimeModified), SIGNAL(timeout()), this, SLOT(slotCheckModified())); m_Data->m_TimeUpdates.setParent(this); connect(&(m_Data->m_TimeUpdates), SIGNAL(timeout()), this, SLOT(slotCheckUpdates())); m_Data->m_resizeColumnsTimer.setSingleShot(true); m_Data->m_resizeColumnsTimer.setParent(this); connect(&(m_Data->m_resizeColumnsTimer), SIGNAL(timeout()), this, SLOT(resizeAllColumns())); } MainTreeWidget::~MainTreeWidget() { delete m_Data; } void MainTreeWidget::_openUrl(const QUrl &url) { openUrl(url, true); } void MainTreeWidget::resizeAllColumns() { m_TreeView->resizeColumnToContents(SvnItemModel::Name); m_TreeView->resizeColumnToContents(SvnItemModel::Status); m_TreeView->resizeColumnToContents(SvnItemModel::LastRevision); m_TreeView->resizeColumnToContents(SvnItemModel::LastAuthor); m_TreeView->resizeColumnToContents(SvnItemModel::LastDate); m_DirTreeView->resizeColumnToContents(SvnItemModel::Name); } bool MainTreeWidget::openUrl(const QUrl &url, bool noReinit) { #ifdef DEBUG_TIMER QTime _counttime; _counttime.start(); #endif CursorStack a; m_Data->m_Model->svnWrapper()->killallThreads(); clear(); emit sigProplist(svn::PathPropertiesMapListPtr(new svn::PathPropertiesMapList()), false, false, QString()); if (!noReinit) { m_Data->m_Model->svnWrapper()->reInitClient(); } QUrl _url(url); const QString proto = svn::Url::transformProtokoll(url.scheme()); _url = _url.adjusted(QUrl::StripTrailingSlash|QUrl::NormalizePathSegments); _url.setScheme(proto); const QString baseUriString = _url.url(QUrl::StripTrailingSlash); const QVector s = baseUriString.splitRef(QLatin1Char('?')); if (s.size() > 1) { setBaseUri(s.first().toString()); } else { setBaseUri(baseUriString); } setWorkingCopy(false); setNetworked(false); m_Data->m_remoteRevision = svn::Revision::HEAD; if (QLatin1String("svn+file") == url.scheme()) { setBaseUri(url.path()); } else { if (url.isLocalFile()) { QFileInfo fi(url.path()); if (fi.exists() && fi.isSymLink()) { const QString sl = fi.readLink(); if (sl.startsWith(QLatin1Char('/'))) { setBaseUri(sl); } else { fi.setFile(fi.path() + QLatin1Char('/') + sl); setBaseUri(fi.absoluteFilePath()); } } else { setBaseUri(url.path()); } QUrl _dummy; qCDebug(KDESVN_LOG) << "check if " << baseUri() << " is a local wc ..."; if (m_Data->m_Model->svnWrapper()->isLocalWorkingCopy(baseUri(), _dummy)) { setWorkingCopy(true); // make sure a valid path is stored as baseuri setBaseUri(url.toLocalFile()); qCDebug(KDESVN_LOG) << "... yes -> " << baseUri(); } else { setWorkingCopy(false); // make sure a valid url is stored as baseuri setBaseUri(url.toString()); qCDebug(KDESVN_LOG) << "... no -> " << baseUri(); } } else { setNetworked(true); if (!Kdesvnsettings::network_on()) { setBaseUri(QString()); setNetworked(false); clear(); KMessageBox::error(this, i18n("Networked URL to open but networking is disabled.")); emit changeCaption(QString()); emit sigUrlOpend(false); return false; } } } const QList> q = QUrlQuery(url).queryItems(); typedef QPair queryPair; Q_FOREACH(const queryPair &p, q) { if (p.first == QLatin1String("rev")) { const QString v = p.second; svn::Revision tmp; m_Data->m_Model->svnWrapper()->svnclient()->url2Revision(v, m_Data->m_remoteRevision, tmp); if (m_Data->m_remoteRevision == svn::Revision::UNDEFINED) { m_Data->m_remoteRevision = svn::Revision::HEAD; } } } if (url.scheme() == QLatin1String("svn+ssh") || url.scheme() == QLatin1String("ksvn+ssh")) { SshAgent ssh; ssh.addSshIdentities(); } m_Data->m_Model->svnWrapper()->clearUpdateCache(); if (isWorkingCopy()) { m_Data->m_Model->initDirWatch(); } - bool result = m_Data->m_Model->checkDirs(baseUri(), 0) > -1; + bool result = m_Data->m_Model->checkDirs(baseUri(), nullptr) > -1; if (result && isWorkingCopy()) { m_Data->m_Model->svnWrapper()->createModifiedCache(baseUri()); m_DirTreeView->expandToDepth(0); m_DirTreeView->selectionModel()->select(m_Data->m_DirSortModel->mapFromSource(m_Data->m_Model->firstRootIndex()), QItemSelectionModel::Select); } resizeAllColumns(); if (!result) { setBaseUri(QString()); setNetworked(false); clear(); } if (result && isWorkingCopy()) { m_Data->m_Model->svnWrapper()->createModifiedCache(baseUri()); if (Kdesvnsettings::start_updates_check_on_open()) { slotCheckUpdates(); } } #ifdef DEBUG_TIMER _counttime.restart(); #endif if (result && Kdesvnsettings::log_cache_on_open()) { m_Data->m_Model->svnWrapper()->startFillCache(baseUri(), true); } #ifdef DEBUG_TIMER qCDebug(KDESVN_LOG) << "Starting cache " << _counttime.elapsed(); _counttime.restart(); #endif emit changeCaption(baseUri()); emit sigUrlOpend(result); emit sigUrlChanged(baseUriAsUrl()); #ifdef DEBUG_TIMER qCDebug(KDESVN_LOG) << "Fired signals " << _counttime.elapsed(); _counttime.restart(); #endif QTimer::singleShot(1, this, SLOT(readSupportData())); enableActions(); #ifdef DEBUG_TIMER qCDebug(KDESVN_LOG) << "Enabled actions " << _counttime.elapsed(); #endif /* KNotification * notification=new KNotification("kdesvn-open"); notification->setText("Opened url"); notification->sendEvent(); */ return result; } void MainTreeWidget::clear() { m_Data->m_Model->clear(); } svn::Revision MainTreeWidget::baseRevision()const { return m_Data->m_remoteRevision; } QWidget *MainTreeWidget::realWidget() { return this; } int MainTreeWidget::selectionCount()const { int count = m_TreeView->selectionModel()->selectedRows(0).count(); if (count == 0) { if (m_TreeView->rootIndex().isValid()) { return 1; } } return count; } int MainTreeWidget::DirselectionCount()const { return m_DirTreeView->selectionModel()->selectedRows(0).count(); } SvnItemList MainTreeWidget::SelectionList()const { SvnItemList ret; const QModelIndexList _mi = m_TreeView->selectionModel()->selectedRows(0); ret.reserve(_mi.size()); if (_mi.isEmpty()) { QModelIndex ind = m_TreeView->rootIndex(); if (ind.isValid()) { // really! it will remapped to this before setRootIndex! (see below) ret.push_back(m_Data->sourceNode(ind, false)); } return ret; } for (int i = 0; i < _mi.count(); ++i) { ret.push_back(m_Data->sourceNode(_mi[i], false)); } return ret; } SvnItemList MainTreeWidget::DirSelectionList()const { SvnItemList ret; const QModelIndexList _mi = m_DirTreeView->selectionModel()->selectedRows(0); ret.reserve(_mi.size()); for (int i = 0; i < _mi.count(); ++i) { ret.push_back(m_Data->sourceNode(_mi[i], true)); } return ret; } QModelIndex MainTreeWidget::SelectedIndex()const { const QModelIndexList _mi = m_TreeView->selectionModel()->selectedRows(0); if (_mi.count() != 1) { if (_mi.isEmpty()) { const QModelIndex ind = m_TreeView->rootIndex(); if (ind.isValid()) { return m_Data->m_SortModel->mapToSource(ind); } } return QModelIndex(); } return m_Data->m_SortModel->mapToSource(_mi[0]); } QModelIndex MainTreeWidget::DirSelectedIndex()const { const QModelIndexList _mi = m_DirTreeView->selectionModel()->selectedRows(0); if (_mi.count() != 1) { return QModelIndex(); } return m_Data->m_DirSortModel->mapToSource(_mi[0]); } SvnItemModelNode *MainTreeWidget::SelectedNode()const { const QModelIndex index = SelectedIndex(); if (index.isValid()) { SvnItemModelNode *item = static_cast(index.internalPointer()); return item; } return nullptr; } SvnItemModelNode *MainTreeWidget::DirSelectedNode()const { const QModelIndex index = DirSelectedIndex(); if (index.isValid()) { SvnItemModelNode *item = static_cast(index.internalPointer()); return item; } return nullptr; } void MainTreeWidget::slotSelectionChanged(const QItemSelection &, const QItemSelection &) { enableActions(); QTimer::singleShot(100, this, SLOT(_propListTimeout())); } SvnItem *MainTreeWidget::Selected()const { return SelectedNode(); } SvnItem *MainTreeWidget::DirSelected()const { return DirSelectedNode(); } SvnItem *MainTreeWidget::DirSelectedOrMain()const { SvnItem *_item = DirSelected(); - if (_item == 0 && isWorkingCopy()) { + if (_item == nullptr && isWorkingCopy()) { _item = m_Data->m_Model->firstRootChild(); } return _item; } SvnItem *MainTreeWidget::SelectedOrMain()const { SvnItem *_item = Selected(); - if (_item == 0 && isWorkingCopy()) { + if (_item == nullptr && isWorkingCopy()) { _item = m_Data->m_Model->firstRootChild(); } return _item; } void MainTreeWidget::setupActions() { if (!m_Data->m_Collection) { return; } QAction *tmp_action; /* local and remote actions */ /* 1. actions on dirs AND files */ tmp_action = add_action(QStringLiteral("make_svn_log_full"), i18n("History of item"), QKeySequence(Qt::CTRL | Qt::Key_L), QIcon::fromTheme(QStringLiteral("kdesvnlog")), this, SLOT(slotMakeLog())); tmp_action->setIconText(i18n("History")); tmp_action->setStatusTip(i18n("Displays the history log of selected item")); tmp_action = add_action(QStringLiteral("make_svn_log_nofollow"), i18n("History of item ignoring copies"), QKeySequence(Qt::SHIFT | Qt::CTRL | Qt::Key_L), QIcon::fromTheme(QStringLiteral("kdesvnlog")), this, SLOT(slotMakeLogNoFollow())); tmp_action->setIconText(i18n("History")); tmp_action->setStatusTip(i18n("Displays the history log of selected item without following copies")); tmp_action = add_action(QStringLiteral("make_svn_dir_log_nofollow"), i18n("History of item ignoring copies"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnlog")), this, SLOT(slotDirMakeLogNoFollow())); tmp_action->setIconText(i18n("History")); tmp_action->setStatusTip(i18n("Displays the history log of selected item without following copies")); tmp_action = add_action(QStringLiteral("make_svn_tree"), i18n("Full revision tree"), QKeySequence(Qt::CTRL | Qt::Key_T), QIcon::fromTheme(QStringLiteral("kdesvntree")), this, SLOT(slotMakeTree())); tmp_action->setStatusTip(i18n("Shows history of item as linked tree")); tmp_action = add_action(QStringLiteral("make_svn_partialtree"), i18n("Partial revision tree"), QKeySequence(Qt::SHIFT | Qt::CTRL | Qt::Key_T), QIcon::fromTheme(QStringLiteral("kdesvntree")), this, SLOT(slotMakePartTree())); tmp_action->setStatusTip(i18n("Shows history of item as linked tree for a revision range")); tmp_action = add_action(QStringLiteral("make_svn_property"), i18n("Properties"), QKeySequence(Qt::CTRL | Qt::Key_P), QIcon(), this, SLOT(slotRightProperties())); tmp_action = add_action(QStringLiteral("make_left_svn_property"), i18n("Properties"), QKeySequence(), QIcon(), this, SLOT(slotLeftProperties())); add_action(QStringLiteral("get_svn_property"), i18n("Display Properties"), QKeySequence(Qt::SHIFT | Qt::CTRL | Qt::Key_P), QIcon(), this, SLOT(slotDisplayProperties())); tmp_action = add_action(QStringLiteral("make_last_change"), i18n("Display last changes"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvndiff")), this, SLOT(slotDisplayLastDiff())); tmp_action->setToolTip(i18n("Display last changes as difference to previous commit.")); tmp_action = add_action(QStringLiteral("make_svn_info"), i18n("Details"), QKeySequence(Qt::CTRL | Qt::Key_I), QIcon::fromTheme(QStringLiteral("kdesvninfo")), this, SLOT(slotInfo())); tmp_action->setStatusTip(i18n("Show details about selected item")); tmp_action = add_action(QStringLiteral("make_svn_rename"), i18n("Move"), QKeySequence(Qt::Key_F2), QIcon::fromTheme(QStringLiteral("kdesvnmove")), this, SLOT(slotRename())); tmp_action->setStatusTip(i18n("Moves or renames current item")); tmp_action = add_action(QStringLiteral("make_svn_copy"), i18n("Copy"), QKeySequence(Qt::CTRL | Qt::Key_C), QIcon::fromTheme(QStringLiteral("kdesvncopy")), this, SLOT(slotCopy())); tmp_action->setStatusTip(i18n("Create a copy of current item")); tmp_action = add_action(QStringLiteral("make_check_updates"), i18n("Check for updates"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvncheckupdates")), this, SLOT(slotCheckUpdates())); tmp_action->setToolTip(i18n("Check if current working copy has items with newer version in repository")); tmp_action->setStatusTip(tmp_action->toolTip()); tmp_action->setIconText(i18n("Check updates")); /* 2. actions only on files */ tmp_action = add_action(QStringLiteral("make_svn_blame"), i18n("Blame"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnblame")), this, SLOT(slotBlame())); tmp_action->setToolTip(i18n("Output the content of specified files or URLs with revision and author information in-line.")); tmp_action->setStatusTip(tmp_action->toolTip()); tmp_action = add_action(QStringLiteral("make_svn_range_blame"), i18n("Blame range"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnblame")), this, SLOT(slotRangeBlame())); tmp_action->setToolTip(i18n("Output the content of specified files or URLs with revision and author information in-line.")); tmp_action->setStatusTip(tmp_action->toolTip()); tmp_action = add_action(QStringLiteral("make_svn_cat"), i18n("Cat head"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvncat")), this, SLOT(slotCat())); tmp_action->setToolTip(i18n("Output the content of specified files or URLs.")); tmp_action->setStatusTip(tmp_action->toolTip()); tmp_action = add_action(QStringLiteral("make_revisions_cat"), i18n("Cat revision..."), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvncat")), this, SLOT(slotRevisionCat())); tmp_action->setToolTip(i18n("Output the content of specified files or URLs at specific revision.")); tmp_action->setStatusTip(tmp_action->toolTip()); tmp_action = add_action(QStringLiteral("make_svn_lock"), i18n("Lock current items"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnlock")), this, SLOT(slotLock())); tmp_action->setToolTip(i18n("Try lock current item against changes from other users")); tmp_action->setStatusTip(tmp_action->toolTip()); tmp_action = add_action(QStringLiteral("make_svn_unlock"), i18n("Unlock current items"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnunlock")), this, SLOT(slotUnlock())); tmp_action->setToolTip(i18n("Free existing lock on current item")); tmp_action->setStatusTip(tmp_action->toolTip()); /* 3. actions only on dirs */ tmp_action = add_action(QStringLiteral("make_svn_mkdir"), i18n("New folder"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnnewfolder")), this, SLOT(slotMkdir())); tmp_action->setStatusTip(i18n("Create a new folder")); tmp_action = add_action(QStringLiteral("make_svn_switch"), i18n("Switch repository"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnswitch")), m_Data->m_Model->svnWrapper(), SLOT(slotSwitch())); tmp_action->setToolTip(i18n("Switch repository path of current working copy path (\"svn switch\")")); tmp_action->setStatusTip(tmp_action->toolTip()); tmp_action = add_action(QStringLiteral("make_svn_relocate"), i18n("Relocate current working copy URL"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnrelocate")), this, SLOT(slotRelocate())); tmp_action->setToolTip(i18n("Relocate URL of current working copy path to other URL")); tmp_action->setStatusTip(tmp_action->toolTip()); tmp_action = add_action(QStringLiteral("make_check_unversioned"), i18n("Check for unversioned items"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnaddrecursive")), this, SLOT(slotCheckNewItems())); tmp_action->setIconText(i18n("Unversioned")); tmp_action->setToolTip(i18n("Browse folder for unversioned items and add them if wanted.")); tmp_action->setStatusTip(tmp_action->toolTip()); tmp_action = add_action(QStringLiteral("make_switch_to_repo"), i18n("Open repository of working copy"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnrepository")), this, SLOT(slotChangeToRepository())); tmp_action->setToolTip(i18n("Opens the repository the current working copy was checked out from")); tmp_action = add_action(QStringLiteral("make_cleanup"), i18n("Cleanup"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvncleanup")), this, SLOT(slotCleanupAction())); tmp_action->setToolTip(i18n("Recursively clean up the working copy, removing locks, resuming unfinished operations, etc.")); tmp_action = add_action(QStringLiteral("make_import_dirs_into_current"), i18n("Import folders into current"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnimportfolder")), this, SLOT(slotImportDirsIntoCurrent())); tmp_action->setToolTip(i18n("Import folder content into current URL")); /* local only actions */ /* 1. actions on files AND dirs*/ tmp_action = add_action(QStringLiteral("make_svn_add"), i18n("Add selected files/dirs"), QKeySequence(Qt::Key_Insert), QIcon::fromTheme(QStringLiteral("kdesvnadd")), m_Data->m_Model->svnWrapper(), SLOT(slotAdd())); tmp_action->setToolTip(i18n("Adding selected files and/or directories to repository")); tmp_action->setIconText(i18n("Add")); tmp_action = add_action(QStringLiteral("make_svn_addrec"), i18n("Add selected files/dirs recursive"), QKeySequence(Qt::CTRL | Qt::Key_Insert), QIcon::fromTheme(QStringLiteral("kdesvnaddrecursive")), m_Data->m_Model->svnWrapper(), SLOT(slotAddRec())); tmp_action->setToolTip(i18n("Adding selected files and/or directories to repository and all subitems of folders")); tmp_action = add_action(QStringLiteral("make_svn_remove"), i18n("Delete selected files/dirs"), QKeySequence(Qt::Key_Delete), QIcon::fromTheme(QStringLiteral("kdesvndelete")), this, SLOT(slotDelete())); tmp_action->setIconText(i18n("Delete")); tmp_action->setToolTip(i18n("Deleting selected files and/or directories from repository")); tmp_action = add_action(QStringLiteral("make_svn_remove_left"), i18n("Delete folder"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvndelete")), this, SLOT(slotLeftDelete())); tmp_action->setToolTip(i18n("Deleting selected directories from repository")); tmp_action->setIconText(i18n("Delete")); tmp_action = add_action(QStringLiteral("make_svn_revert"), i18n("Revert current changes"), QKeySequence(Qt::CTRL | Qt::Key_R), QIcon::fromTheme(QStringLiteral("kdesvnreverse")), m_Data->m_Model->svnWrapper(), SLOT(slotRevert())); tmp_action = add_action(QStringLiteral("make_resolved"), i18n("Mark resolved"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnresolved")), this, SLOT(slotResolved())); tmp_action->setToolTip(i18n("Marking files or dirs resolved")); tmp_action = add_action(QStringLiteral("make_try_resolve"), i18n("Resolve conflicts"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnresolved")), this, SLOT(slotTryResolve())); tmp_action = add_action(QStringLiteral("make_svn_ignore"), i18n("Ignore/Unignore current item"), QKeySequence(), QIcon(), this, SLOT(slotIgnore())); tmp_action = add_action(QStringLiteral("make_left_add_ignore_pattern"), i18n("Add or Remove ignore pattern"), QKeySequence(), QIcon(), this, SLOT(slotLeftRecAddIgnore())); tmp_action = add_action(QStringLiteral("make_right_add_ignore_pattern"), i18n("Add or Remove ignore pattern"), QKeySequence(), QIcon(), this, SLOT(slotRightRecAddIgnore())); tmp_action = add_action(QStringLiteral("make_svn_headupdate"), i18n("Update to head"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnupdate")), m_Data->m_Model->svnWrapper(), SLOT(slotUpdateHeadRec())); tmp_action->setIconText(i18nc("Menu item", "Update")); tmp_action = add_action(QStringLiteral("make_svn_revupdate"), i18n("Update to revision..."), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnupdate")), m_Data->m_Model->svnWrapper(), SLOT(slotUpdateTo())); tmp_action = add_action(QStringLiteral("make_svn_commit"), i18n("Commit"), QKeySequence(QStringLiteral("CTRL+#")), QIcon::fromTheme(QStringLiteral("kdesvncommit")), this, SLOT(slotCommit())); tmp_action->setIconText(i18n("Commit")); tmp_action = add_action(QStringLiteral("make_svn_basediff"), i18n("Diff local changes"), QKeySequence(Qt::CTRL | Qt::Key_D), QIcon::fromTheme(QStringLiteral("kdesvndiff")), this, SLOT(slotSimpleBaseDiff())); tmp_action->setToolTip(i18n("Diff working copy against BASE (last checked out version) - does not require access to repository")); tmp_action = add_action(QStringLiteral("make_svn_dirbasediff"), i18n("Diff local changes"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvndiff")), this, SLOT(slotDirSimpleBaseDiff())); tmp_action->setToolTip(i18n("Diff working copy against BASE (last checked out version) - does not require access to repository")); tmp_action = add_action(QStringLiteral("make_svn_headdiff"), i18n("Diff against HEAD"), QKeySequence(Qt::CTRL | Qt::Key_H), QIcon::fromTheme(QStringLiteral("kdesvndiff")), this, SLOT(slotSimpleHeadDiff())); tmp_action->setToolTip(i18n("Diff working copy against HEAD (last checked in version)- requires access to repository")); tmp_action = add_action(QStringLiteral("make_svn_itemsdiff"), i18n("Diff items"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvndiff")), this, SLOT(slotDiffPathes())); tmp_action->setToolTip(i18n("Diff two items")); tmp_action = add_action(QStringLiteral("make_svn_diritemsdiff"), i18n("Diff items"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvndiff")), this, SLOT(slotDiffPathes())); tmp_action->setToolTip(i18n("Diff two items")); tmp_action = add_action(QStringLiteral("make_svn_merge_revisions"), i18n("Merge two revisions"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnmerge")), this, SLOT(slotMergeRevisions())); tmp_action->setIconText(i18n("Merge")); tmp_action->setToolTip(i18n("Merge two revisions of this entry into itself")); tmp_action = add_action(QStringLiteral("make_svn_merge"), i18n("Merge..."), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnmerge")), this, SLOT(slotMerge())); tmp_action->setToolTip(i18n("Merge repository path into current working copy path or current repository path into a target")); tmp_action = add_action(QStringLiteral("openwith"), i18n("Open With..."), QKeySequence(), QIcon(), this, SLOT(slotOpenWith())); /* remote actions only */ tmp_action = add_action(QStringLiteral("make_svn_checkout_current"), i18n("Checkout current repository path"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvncheckout")), m_Data->m_Model->svnWrapper(), SLOT(slotCheckoutCurrent())); tmp_action->setIconText(i18n("Checkout")); tmp_action = add_action(QStringLiteral("make_svn_export_current"), i18n("Export current repository path"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnexport")), m_Data->m_Model->svnWrapper(), SLOT(slotExportCurrent())); add_action(QStringLiteral("switch_browse_revision"), i18n("Select browse revision"), QKeySequence(), QIcon(), this, SLOT(slotSelectBrowsingRevision())); /* independe actions */ tmp_action = add_action(QStringLiteral("make_svn_checkout"), i18n("Checkout a repository"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvncheckout")), m_Data->m_Model->svnWrapper(), SLOT(slotCheckout())); tmp_action->setIconText(i18n("Checkout")); tmp_action = add_action(QStringLiteral("make_svn_export"), i18n("Export a repository"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnexport")), m_Data->m_Model->svnWrapper(), SLOT(slotExport())); tmp_action->setIconText(i18n("Export")); tmp_action = add_action(QStringLiteral("make_view_refresh"), i18n("Refresh view"), QKeySequence(Qt::Key_F5), QIcon::fromTheme(QStringLiteral("kdesvnrightreload")), this, SLOT(refreshCurrentTree())); tmp_action->setIconText(i18n("Refresh")); add_action(QStringLiteral("make_revisions_diff"), i18n("Diff revisions"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvndiff")), this, SLOT(slotDiffRevisions())); /* folding options */ tmp_action = add_action(QStringLiteral("view_unfold_tree"), i18n("Unfold File Tree"), QKeySequence(), QIcon(), this, SLOT(slotUnfoldTree())); tmp_action->setToolTip(i18n("Opens all branches of the file tree")); tmp_action = add_action(QStringLiteral("view_fold_tree"), i18n("Fold File Tree"), QKeySequence(), QIcon(), this , SLOT(slotFoldTree())); tmp_action->setToolTip(i18n("Closes all branches of the file tree")); /* caching */ tmp_action = add_action(QStringLiteral("update_log_cache"), i18n("Update log cache"), QKeySequence(), QIcon(), this, SLOT(slotUpdateLogCache())); tmp_action->setToolTip(i18n("Update the log cache for current repository")); tmp_action = add_action(QStringLiteral("make_dir_commit"), i18n("Commit"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvncommit")), this, SLOT(slotDirCommit())); tmp_action = add_action(QStringLiteral("make_dir_update"), i18n("Update to head"), QKeySequence(), QIcon::fromTheme(QStringLiteral("kdesvnupdate")), this, SLOT(slotDirUpdate())); tmp_action = add_action(QStringLiteral("set_rec_property_dir"), i18n("Set property recursive"), QKeySequence(), QIcon(), this, SLOT(slotDirRecProperty())); tmp_action = add_action(QStringLiteral("show_repository_settings"), i18n("Settings for current repository"), QKeySequence(), QIcon(), this, SLOT(slotRepositorySettings())); enableActions(); } bool MainTreeWidget::uniqueTypeSelected() { QModelIndexList _mi = m_TreeView->selectionModel()->selectedRows(0); if (_mi.count() < 1) { return false; } bool dir = static_cast(m_Data->srcInd(_mi[0]).internalPointer())->isDir(); for (int i = 1; i < _mi.count(); ++i) { if (static_cast(m_Data->srcInd(_mi[i]).internalPointer())->isDir() != dir) { return false; } } return true; } void MainTreeWidget::enableAction(const QString &name, bool how) { QAction *temp = filesActions()->action(name); if (temp) { temp->setEnabled(how); temp->setVisible(how); } } void MainTreeWidget::enableActions() { const bool isopen = !baseUri().isEmpty(); const SvnItemList fileList = SelectionList(); const SvnItemList dirList = DirSelectionList(); const SvnItemModelNode *si = SelectedNode(); const bool single = isopen && fileList.size() == 1; const bool multi = isopen && fileList.size() > 1; const bool none = isopen && fileList.isEmpty(); const bool single_dir = single && si && si->isDir(); const bool unique = uniqueTypeSelected(); const bool remote_enabled =/*isopen&&*/m_Data->m_Model->svnWrapper()->doNetworking(); const bool conflicted = single && si && si->isConflicted(); bool at_least_one_changed = false; bool at_least_one_conflicted = false; bool at_least_one_local_added = false; bool all_unversioned = true; bool all_versioned = true; bool at_least_one_directory = false; for(int i = 0; i < fileList.size(); ++i) { const SvnItem *item = fileList.at(i); if (!item) { // root item continue; } if (item->isChanged()) { at_least_one_changed = true; } if (item->isConflicted()) { at_least_one_conflicted = true; } if (item->isLocalAdded()) { at_least_one_local_added = true; } if (item->isRealVersioned()) { all_unversioned = false; } else { all_versioned = false; } if (item->isDir()) { at_least_one_directory = true; } } //qDebug("single: %d, multi: %d, none: %d, single_dir: %d, unique: %d, remove_enabled: %d, conflicted: %d, changed: %d, added: %d", // single, multi, none, single_dir, unique, remote_enabled, conflicted, si && si->isChanged(), si && si->isLocalAdded()); //qDebug("at_least_one_changed: %d, at_least_one_conflicted: %d, at_least_one_local_added: %d, all_unversioned: %d, all_versioned: %d, at_least_one_directory: %d", // at_least_one_changed, at_least_one_conflicted, at_least_one_local_added, all_unversioned, all_versioned, at_least_one_directory); /* local and remote actions */ /* 1. actions on dirs AND files */ enableAction(QStringLiteral("make_svn_log_nofollow"), single || none); enableAction(QStringLiteral("make_svn_dir_log_nofollow"), dirList.size() == 1 && isopen); enableAction(QStringLiteral("make_last_change"), isopen); enableAction(QStringLiteral("make_svn_log_full"), single || none); enableAction(QStringLiteral("make_svn_tree"), single || none); enableAction(QStringLiteral("make_svn_partialtree"), single || none); enableAction(QStringLiteral("make_svn_property"), single); enableAction(QStringLiteral("make_left_svn_property"), dirList.size() == 1); enableAction(QStringLiteral("set_rec_property_dir"), dirList.size() == 1); enableAction(QStringLiteral("get_svn_property"), single); enableAction(QStringLiteral("make_svn_remove"), (multi || single)); enableAction(QStringLiteral("make_svn_remove_left"), dirList.size() > 0); enableAction(QStringLiteral("make_svn_lock"), (multi || single)); enableAction(QStringLiteral("make_svn_unlock"), (multi || single)); - enableAction(QStringLiteral("make_svn_ignore"), (single) && si && si->parent() != 0 && !si->isRealVersioned()); + enableAction(QStringLiteral("make_svn_ignore"), (single) && si && si->parent() != nullptr && !si->isRealVersioned()); enableAction(QStringLiteral("make_left_add_ignore_pattern"), (dirList.size() == 1) && isWorkingCopy()); enableAction(QStringLiteral("make_right_add_ignore_pattern"), single_dir && isWorkingCopy()); enableAction(QStringLiteral("make_svn_rename"), single && (!isWorkingCopy() || si != m_Data->m_Model->firstRootChild())); enableAction(QStringLiteral("make_svn_copy"), single && (!isWorkingCopy() || si != m_Data->m_Model->firstRootChild())); /* 2. only on files */ enableAction(QStringLiteral("make_svn_blame"), single && !single_dir && remote_enabled); enableAction(QStringLiteral("make_svn_range_blame"), single && !single_dir && remote_enabled); enableAction(QStringLiteral("make_svn_cat"), single && !single_dir); /* 3. actions only on dirs */ enableAction(QStringLiteral("make_svn_mkdir"), single_dir || (none && isopen)); enableAction(QStringLiteral("make_svn_switch"), isWorkingCopy() && (single || none)); enableAction(QStringLiteral("make_switch_to_repo"), isWorkingCopy()); enableAction(QStringLiteral("make_import_dirs_into_current"), single_dir || dirList.size() == 1); enableAction(QStringLiteral("make_svn_relocate"), isWorkingCopy() && (single || none)); enableAction(QStringLiteral("make_svn_export_current"), ((single && single_dir) || none)); /* local only actions */ /* 1. actions on files AND dirs*/ enableAction(QStringLiteral("make_svn_add"), (multi || single) && isWorkingCopy() && all_unversioned); enableAction(QStringLiteral("make_svn_revert"), (multi || single) && isWorkingCopy() && (at_least_one_changed || at_least_one_conflicted || at_least_one_local_added)); enableAction(QStringLiteral("make_resolved"), (multi || single) && isWorkingCopy()); enableAction(QStringLiteral("make_try_resolve"), conflicted && !single_dir); enableAction(QStringLiteral("make_svn_info"), isopen); enableAction(QStringLiteral("make_svn_merge_revisions"), (single || dirList.size() == 1) && isWorkingCopy()); enableAction(QStringLiteral("make_svn_merge"), single || dirList.size() == 1 || none); enableAction(QStringLiteral("make_svn_addrec"), (multi || single) && at_least_one_directory && isWorkingCopy() && all_unversioned); enableAction(QStringLiteral("make_svn_headupdate"), isWorkingCopy() && isopen && remote_enabled); enableAction(QStringLiteral("make_dir_update"), isWorkingCopy() && isopen && remote_enabled); enableAction(QStringLiteral("make_svn_revupdate"), isWorkingCopy() && isopen && remote_enabled); enableAction(QStringLiteral("make_svn_commit"), isWorkingCopy() && isopen && remote_enabled); enableAction(QStringLiteral("make_dir_commit"), isWorkingCopy() && isopen && remote_enabled); enableAction(QStringLiteral("make_svn_basediff"), isWorkingCopy() && (single || none)); enableAction(QStringLiteral("make_svn_dirbasediff"), isWorkingCopy() && (dirList.size() < 2)); enableAction(QStringLiteral("make_svn_headdiff"), isWorkingCopy() && (single || none) && remote_enabled); /// @todo check if all items have same type enableAction(QStringLiteral("make_svn_itemsdiff"), multi && fileList.size() == 2 && unique && remote_enabled && all_versioned); enableAction(QStringLiteral("make_svn_diritemsdiff"), dirList.size() == 2 && isopen && remote_enabled && all_versioned); /* 2. on dirs only */ enableAction(QStringLiteral("make_cleanup"), isWorkingCopy() && (single_dir || none)); enableAction(QStringLiteral("make_check_unversioned"), isWorkingCopy() && ((single_dir && single) || none)); /* remote actions only */ enableAction(QStringLiteral("make_svn_checkout_current"), ((single && single_dir) || none) && !isWorkingCopy() && remote_enabled); /* independ actions */ enableAction(QStringLiteral("make_svn_checkout"), remote_enabled); enableAction(QStringLiteral("make_svn_export"), true); enableAction(QStringLiteral("make_view_refresh"), isopen); enableAction(QStringLiteral("make_revisions_diff"), isopen); enableAction(QStringLiteral("make_revisions_cat"), isopen && !single_dir && single); enableAction(QStringLiteral("switch_browse_revision"), !isWorkingCopy() && isopen); enableAction(QStringLiteral("make_check_updates"), isWorkingCopy() && isopen && remote_enabled); enableAction(QStringLiteral("openwith"), KAuthorized::authorizeAction("openwith") && single && !single_dir); enableAction(QStringLiteral("show_repository_settings"), isopen); enableAction(QStringLiteral("repo_statistic"), isopen); QAction *temp = filesActions()->action(QStringLiteral("update_log_cache")); if (temp) { temp->setEnabled(remote_enabled); if (!m_Data->m_Model->svnWrapper()->threadRunning(SvnActions::fillcachethread)) { temp->setText(i18n("Update log cache")); } else { temp->setText(i18n("Stop updating the log cache")); } } } QAction *MainTreeWidget::add_action(const QString &actionname, const QString &text, const QKeySequence &sequ, const QIcon &icon, QObject *target, const char *slot) { - QAction *tmp_action = 0; + QAction *tmp_action = nullptr; tmp_action = m_Data->m_Collection->addAction(actionname, target, slot); tmp_action->setText(text); m_Data->m_Collection->setDefaultShortcut(tmp_action, sequ); tmp_action->setIcon(icon); return tmp_action; } KActionCollection *MainTreeWidget::filesActions() { return m_Data->m_Collection; } void MainTreeWidget::closeMe() { m_Data->m_Model->svnWrapper()->killallThreads(); clear(); setWorkingCopy(true); setNetworked(false); setWorkingCopy(false); setBaseUri(QString()); emit changeCaption(QString()); emit sigUrlOpend(false); emit sigUrlChanged(QUrl()); enableActions(); m_Data->m_Model->svnWrapper()->reInitClient(); } void MainTreeWidget::refreshCurrentTree() { m_Data->m_Model->refreshCurrentTree(); if (isWorkingCopy()) { m_Data->m_Model->svnWrapper()->createModifiedCache(baseUri()); } m_Data->m_SortModel->invalidate(); setUpdatesEnabled(true); //viewport()->repaint(); QTimer::singleShot(1, this, SLOT(readSupportData())); } void MainTreeWidget::slotSettingsChanged() { m_Data->m_SortModel->setSortCaseSensitivity(Kdesvnsettings::case_sensitive_sort() ? Qt::CaseSensitive : Qt::CaseInsensitive); m_Data->m_SortModel->invalidate(); m_Data->m_DirSortModel->invalidate(); enableActions(); if (m_Data->m_Model->svnWrapper() && !m_Data->m_Model->svnWrapper()->doNetworking()) { m_Data->m_Model->svnWrapper()->stopFillCache(); } checkUseNavigation(); } KService::List MainTreeWidget::offersList(SvnItem *item, bool execOnly) const { KService::List offers; if (!item) { return offers; } if (!item->mimeType().isValid()) { return offers; } QString constraint(QLatin1String("(DesktopEntryName != 'kdesvn') and (Type == 'Application')")); if (execOnly) { constraint += QLatin1String(" and (exist Exec)"); } offers = KMimeTypeTrader::self()->query(item->mimeType().name(), QString::fromLatin1("Application"), constraint); return offers; } void MainTreeWidget::slotItemActivated(const QModelIndex &_index) { QModelIndex index = m_Data->m_SortModel->mapToSource(_index); itemActivated(index); } void MainTreeWidget::itemActivated(const QModelIndex &index, bool keypress) { Q_UNUSED(keypress); SvnItemModelNode *item; if (index.isValid() && (item = static_cast(index.internalPointer()))) { if (!item->isDir()) { svn::Revision rev; QList lst; lst.append(item->kdeName(rev)); KService::List li = offersList(item, true); if (li.isEmpty() || li.first()->exec().isEmpty()) { li = offersList(item); } if (!li.isEmpty() && !li.first()->exec().isEmpty()) { KService::Ptr ptr = li.first(); KRun::runService(*ptr, lst, QApplication::activeWindow()); } else { KRun::displayOpenWithDialog(lst, QApplication::activeWindow()); } } else if (Kdesvnsettings::show_navigation_panel()) { m_DirTreeView->selectionModel()->select(m_Data->m_DirSortModel->mapFromSource(index), QItemSelectionModel::ClearAndSelect); QModelIndex _ind = m_Data->m_Model->parent(index); if (_ind.isValid()) { m_DirTreeView->expand(m_Data->m_DirSortModel->mapFromSource(_ind)); } } else { } } } void MainTreeWidget::slotCheckUpdates() { if (isWorkingCopy() && m_Data->m_Model->svnWrapper()->doNetworking()) { m_Data->m_TimeUpdates.stop(); m_Data->m_Model->svnWrapper()->createUpdateCache(baseUri()); } } void MainTreeWidget::slotCheckModified() { if (isWorkingCopy()) { m_Data->m_TimeModified.stop(); m_Data->m_Model->svnWrapper()->createModifiedCache(baseUri()); } } void MainTreeWidget::slotNotifyMessage(const QString &what) { emit sigLogMessage(what); QCoreApplication::processEvents(); } void MainTreeWidget::readSupportData() { /// this moment empty cause no usagedata explicit used by MainTreeWidget } void MainTreeWidget::slotClientException(const QString &what) { emit sigLogMessage(what); KMessageBox::sorry(QApplication::activeModalWidget(), what, i18n("SVN Error")); } void MainTreeWidget::slotCacheDataChanged() { m_Data->m_SortModel->invalidate(); if (isWorkingCopy()) { if (!m_Data->m_TimeModified.isActive() && Kdesvnsettings::poll_modified()) { m_Data->m_TimeModified.setInterval(MinutesToMsec(Kdesvnsettings::poll_modified_minutes())); m_Data->m_TimeModified.start(); } if (!m_Data->m_TimeUpdates.isActive() && Kdesvnsettings::poll_updates()) { m_Data->m_TimeUpdates.setInterval(MinutesToMsec(Kdesvnsettings::poll_updates_minutes())); m_Data->m_TimeUpdates.start(); } } } void MainTreeWidget::slotIgnore() { m_Data->m_Model->makeIgnore(SelectedIndex()); m_Data->m_SortModel->invalidate(); } void MainTreeWidget::slotLeftRecAddIgnore() { SvnItem *item = DirSelected(); if (!item || !item->isDir()) { return; } recAddIgnore(item); } void MainTreeWidget::slotRightRecAddIgnore() { SvnItem *item = Selected(); if (!item || !item->isDir()) { return; } recAddIgnore(item); } void MainTreeWidget::recAddIgnore(SvnItem *item) { QPointer dlg(new KSvnSimpleOkDialog(QStringLiteral("ignore_pattern_dlg"))); dlg->setWindowTitle(i18nc("@title:window", "Edit Pattern to Ignore for \"%1\"", item->shortName())); dlg->setWithCancelButton(); EditIgnorePattern *ptr(new EditIgnorePattern(dlg)); dlg->addWidget(ptr); if (dlg->exec() != QDialog::Accepted) { delete dlg; return; } svn::Depth _d = ptr->depth(); QStringList _pattern = ptr->items(); bool unignore = ptr->unignore(); svn::Revision start(svn::Revision::WORKING); if (!isWorkingCopy()) { start = baseRevision(); } svn::StatusEntries res; if (!m_Data->m_Model->svnWrapper()->makeStatus(item->fullName(), res, start, _d, true /* all entries */, false, false)) { return; } for (int i = 0; i < res.count(); ++i) { if (!res[i]->isRealVersioned() || res[i]->entry().kind() != svn_node_dir) { continue; } m_Data->m_Model->svnWrapper()->makeIgnoreEntry(res[i]->path(), _pattern, unignore); } refreshCurrentTree(); delete dlg; } void MainTreeWidget::slotMakeLogNoFollow()const { doLog(false, false); } void MainTreeWidget::slotMakeLog()const { doLog(true, false); } void MainTreeWidget::slotDirMakeLogNoFollow()const { doLog(false, true); } void MainTreeWidget::doLog(bool use_follow_settings, bool left)const { SvnItem *k = left ? DirSelectedOrMain() : SelectedOrMain(); QString what; if (k) { what = k->fullName(); } else if (!isWorkingCopy() && selectionCount() == 0) { what = baseUri(); } else { return; } svn::Revision start(svn::Revision::HEAD); if (!isWorkingCopy()) { start = baseRevision(); } svn::Revision end(svn::Revision::START); bool list = Kdesvnsettings::self()->log_always_list_changed_files(); bool follow = use_follow_settings ? Kdesvnsettings::log_follows_nodes() : false; Kdesvnsettings::setLast_node_follow(follow); int l = 50; m_Data->m_Model->svnWrapper()->makeLog(start, end, (isWorkingCopy() ? svn::Revision::UNDEFINED : baseRevision()), what, follow, list, l); } void MainTreeWidget::slotContextMenu(const QPoint &) { execContextMenu(SelectionList()); } void MainTreeWidget::slotDirContextMenu(const QPoint &vp) { QMenu popup; - QAction *temp = 0; + QAction *temp = nullptr; int count = 0; if ((temp = filesActions()->action(QStringLiteral("make_dir_commit"))) && temp->isEnabled() && ++count) { popup.addAction(temp); } if ((temp = filesActions()->action(QStringLiteral("make_dir_update"))) && temp->isEnabled() && ++count) { popup.addAction(temp); } if ((temp = filesActions()->action(QStringLiteral("make_svn_dirbasediff"))) && temp->isEnabled() && ++count) { popup.addAction(temp); } if ((temp = filesActions()->action(QStringLiteral("make_svn_diritemsdiff"))) && temp->isEnabled() && ++count) { popup.addAction(temp); } if ((temp = filesActions()->action(QStringLiteral("make_svn_dir_log_nofollow"))) && temp->isEnabled() && ++count) { popup.addAction(temp); } if ((temp = filesActions()->action(QStringLiteral("make_left_svn_property"))) && temp->isEnabled() && ++count) { popup.addAction(temp); } if ((temp = filesActions()->action(QStringLiteral("make_svn_remove_left"))) && temp->isEnabled() && ++count) { popup.addAction(temp); } if ((temp = filesActions()->action(QStringLiteral("make_left_add_ignore_pattern"))) && temp->isEnabled() && ++count) { popup.addAction(temp); } if ((temp = filesActions()->action(QStringLiteral("set_rec_property_dir"))) && temp->isEnabled() && ++count) { popup.addAction(temp); } OpenContextmenu *me = nullptr; QAction *menuAction = nullptr; const SvnItemList l = DirSelectionList(); if (l.count() == 1 && l.at(0)) { const KService::List offers = offersList(l.at(0), l.at(0)->isDir()); if (!offers.isEmpty()) { svn::Revision rev(isWorkingCopy() ? svn::Revision::UNDEFINED : baseRevision()); - me = new OpenContextmenu(l.at(0)->kdeName(rev), offers, 0); + me = new OpenContextmenu(l.at(0)->kdeName(rev), offers, nullptr); me->setTitle(i18n("Open With...")); menuAction = popup.addMenu(me); ++count; } } if (count) { popup.exec(m_DirTreeView->viewport()->mapToGlobal(vp)); } if (menuAction) { popup.removeAction(menuAction); delete menuAction; } delete me; } void MainTreeWidget::execContextMenu(const SvnItemList &l) { bool isopen = baseUri().length() > 0; QString menuname; if (!isopen) { menuname = "empty"; } else if (isWorkingCopy()) { menuname = "local"; } else { menuname = "remote"; } if (l.isEmpty()) { menuname += "_general"; } else if (l.count() > 1) { menuname += "_context_multi"; } else { menuname += "_context_single"; if (isWorkingCopy()) { if (l.at(0)->isRealVersioned()) { if (l.at(0)->isConflicted()) { menuname += "_conflicted"; } else { menuname += "_versioned"; if (l.at(0)->isDir()) { menuname += "_dir"; } } } else { menuname += "_unversioned"; } } else if (l.at(0)->isDir()) { menuname += "_dir"; } } //qDebug("menuname: %s", qPrintable(menuname)); QWidget *target; emit sigShowPopup(menuname, &target); QMenu *popup = static_cast(target); if (!popup) { return; } OpenContextmenu *me = nullptr; QAction *temp = nullptr; QAction *menuAction = nullptr; if (l.count() == 1/*&&!l.at(0)->isDir()*/) { KService::List offers = offersList(l.at(0), l.at(0)->isDir()); if (!offers.isEmpty()) { svn::Revision rev(isWorkingCopy() ? svn::Revision::UNDEFINED : baseRevision()); - me = new OpenContextmenu(l.at(0)->kdeName(rev), offers, 0); + me = new OpenContextmenu(l.at(0)->kdeName(rev), offers, nullptr); me->setTitle(i18n("Open With...")); menuAction = popup->addMenu(me); } else { temp = filesActions()->action(QStringLiteral("openwith")); if (temp) { popup->addAction(temp); } } } popup->exec(QCursor::pos()); if (menuAction) { popup->removeAction(menuAction); } delete me; if (temp) { popup->removeAction(temp); delete temp; } } void MainTreeWidget::slotUnfoldTree() { m_TreeView->expandAll(); } void MainTreeWidget::slotFoldTree() { m_TreeView->collapseAll(); } void MainTreeWidget::slotOpenWith() { SvnItem *which = Selected(); if (!which || which->isDir()) { return; } svn::Revision rev(isWorkingCopy() ? svn::Revision::UNDEFINED : baseRevision()); QList lst; lst.append(which->kdeName(rev)); KRun::displayOpenWithDialog(lst, QApplication::activeWindow()); } void MainTreeWidget::slotSelectBrowsingRevision() { if (isWorkingCopy()) { return; } Rangeinput_impl::revision_range range; if (Rangeinput_impl::getRevisionRange(range, false)) { m_Data->m_remoteRevision = range.first; clear(); - m_Data->m_Model->checkDirs(baseUri(), 0); + m_Data->m_Model->checkDirs(baseUri(), nullptr); emit changeCaption(baseUri() + QLatin1Char('@') + range.first.toString()); } } void MainTreeWidget::slotMakeTree() { QString what; SvnItem *k = SelectedOrMain(); if (k) { what = k->fullName(); } else if (!isWorkingCopy() && selectionCount() == 0) { what = baseUri(); } else { return; } svn::Revision rev(isWorkingCopy() ? svn::Revision::WORKING : baseRevision()); m_Data->m_Model->svnWrapper()->makeTree(what, rev); } void MainTreeWidget::slotMakePartTree() { QString what; SvnItem *k = SelectedOrMain(); if (k) { what = k->fullName(); } else if (!isWorkingCopy() && selectionCount() == 0) { what = baseUri(); } else { return; } Rangeinput_impl::revision_range range; if (Rangeinput_impl::getRevisionRange(range)) { svn::Revision rev(isWorkingCopy() ? svn::Revision::UNDEFINED : baseRevision()); m_Data->m_Model->svnWrapper()->makeTree(what, rev, range.first, range.second); } } void MainTreeWidget::slotLock() { const SvnItemList lst = SelectionList(); if (lst.isEmpty()) { KMessageBox::error(this, i18n("Nothing selected for unlock")); return; } QPointer dlg(new KSvnSimpleOkDialog(QStringLiteral("locking_log_msg"))); dlg->setWindowTitle(i18nc("@title:window", "Lock Message")); dlg->setWithCancelButton(); Commitmsg_impl *ptr(new Commitmsg_impl(dlg)); ptr->initHistory(); ptr->hideDepth(true); ptr->keepsLocks(false); QCheckBox *_stealLock = new QCheckBox(i18n("Steal lock?")); ptr->addItemWidget(_stealLock); dlg->addWidget(ptr); if (dlg->exec() != QDialog::Accepted) { if (dlg) ptr->saveHistory(true); delete dlg; return; } QString logMessage = ptr->getMessage(); bool steal = _stealLock->isChecked(); ptr->saveHistory(false); QStringList displist; for (int i = 0; i < lst.count(); ++i) { displist.append(lst[i]->fullName()); } m_Data->m_Model->svnWrapper()->makeLock(displist, logMessage, steal); refreshCurrentTree(); delete dlg; } /*! \fn MainTreeWidget::slotUnlock() */ void MainTreeWidget::slotUnlock() { const SvnItemList lst = SelectionList(); if (lst.isEmpty()) { KMessageBox::error(this, i18n("Nothing selected for unlock")); return; } KMessageBox::ButtonCode res = KMessageBox::questionYesNoCancel(this, i18n("Break lock or ignore missing locks?"), i18n("Unlocking items")); if (res == KMessageBox::Cancel) { return; } bool breakit = res == KMessageBox::Yes; QStringList displist; for (int i = 0; i < lst.count(); ++i) { displist.append(lst[i]->fullName()); } m_Data->m_Model->svnWrapper()->makeUnlock(displist, breakit); refreshCurrentTree(); } void MainTreeWidget::slotDisplayLastDiff() { SvnItem *kitem = Selected(); QString what; if (isWorkingCopy()) { QDir::setCurrent(baseUri()); } svn::Revision end = svn::Revision::PREV; if (!kitem) { if (isWorkingCopy()) { kitem = m_Data->m_Model->firstRootChild(); if (!kitem) { return; } what = relativePath(kitem); } else { what = baseUri(); } } else { what = relativePath(kitem); } svn::Revision start; svn::InfoEntry inf; if (!kitem) { // it has to have an item when in working copy, so we know we are in repository view. if (!m_Data->m_Model->svnWrapper()->singleInfo(what, baseRevision(), inf)) { return; } start = inf.cmtRev(); } else { start = kitem->cmtRev(); } if (!isWorkingCopy()) { if (!m_Data->m_Model->svnWrapper()->singleInfo(what, start.revnum() - 1, inf)) { return; } end = inf.cmtRev(); } m_Data->m_Model->svnWrapper()->makeDiff(what, end, what, start, realWidget()); } void MainTreeWidget::slotSimpleBaseDiff() { simpleWcDiff(Selected(), svn::Revision::BASE, svn::Revision::WORKING); } void MainTreeWidget::slotDirSimpleBaseDiff() { simpleWcDiff(DirSelected(), svn::Revision::BASE, svn::Revision::WORKING); } void MainTreeWidget::slotSimpleHeadDiff() { simpleWcDiff(Selected(), svn::Revision::WORKING, svn::Revision::HEAD); } void MainTreeWidget::simpleWcDiff(SvnItem *kitem, const svn::Revision &first, const svn::Revision &second) { QString what; if (isWorkingCopy()) { QDir::setCurrent(baseUri()); } if (!kitem) { what = QLatin1Char('.'); } else { what = relativePath(kitem); } // only possible on working copies - so we may say this values m_Data->m_Model->svnWrapper()->makeDiff(what, first, second, svn::Revision::UNDEFINED, kitem ? kitem->isDir() : true); } void MainTreeWidget::slotDiffRevisions() { SvnItem *k = Selected(); QString what; if (isWorkingCopy()) { QDir::setCurrent(baseUri()); } if (!k) { what = (isWorkingCopy() ? "." : baseUri()); } else { what = relativePath(k); } Rangeinput_impl::revision_range range; if (Rangeinput_impl::getRevisionRange(range)) { svn::Revision _peg = (isWorkingCopy() ? svn::Revision::WORKING : baseRevision()); m_Data->m_Model->svnWrapper()->makeDiff(what, range.first, range.second, _peg, k ? k->isDir() : true); } } void MainTreeWidget::slotDiffPathes() { SvnItemList lst; QObject *tr = sender(); bool unique = false; if (tr == filesActions()->action(QStringLiteral("make_svn_diritemsdiff"))) { unique = true; lst = DirSelectionList(); } else { lst = SelectionList(); } if (lst.count() != 2 || (!unique && !uniqueTypeSelected())) { return; } SvnItem *k1 = lst.at(0); SvnItem *k2 = lst.at(1); QString w1, w2; svn::Revision r1; if (isWorkingCopy()) { QDir::setCurrent(baseUri()); w1 = relativePath(k1); w2 = relativePath(k2); r1 = svn::Revision::WORKING; } else { w1 = k1->fullName(); w2 = k2->fullName(); r1 = baseRevision(); } m_Data->m_Model->svnWrapper()->makeDiff(w1, r1, w2, r1); } void MainTreeWidget::slotInfo() { svn::Revision rev(isWorkingCopy() ? svn::Revision::UNDEFINED : baseRevision()); if (!isWorkingCopy()) { rev = baseRevision(); } SvnItemList lst = SelectionList(); if (lst.isEmpty()) { if (!isWorkingCopy()) { QStringList _sl(baseUri()); m_Data->m_Model->svnWrapper()->makeInfo(_sl, rev, svn::Revision::UNDEFINED, Kdesvnsettings::info_recursive()); } else { lst.append(SelectedOrMain()); } } if (!lst.isEmpty()) { m_Data->m_Model->svnWrapper()->makeInfo(lst, rev, rev, Kdesvnsettings::info_recursive()); } } void MainTreeWidget::slotBlame() { SvnItem *k = Selected(); if (!k) { return; } svn::Revision start(svn::Revision::START); svn::Revision end(svn::Revision::HEAD); m_Data->m_Model->svnWrapper()->makeBlame(start, end, k); } void MainTreeWidget::slotRangeBlame() { SvnItem *k = Selected(); if (!k) { return; } Rangeinput_impl::revision_range range; if (Rangeinput_impl::getRevisionRange(range)) { m_Data->m_Model->svnWrapper()->makeBlame(range.first, range.second, k); } } void MainTreeWidget::_propListTimeout() { dispProperties(false); } void MainTreeWidget::slotDisplayProperties() { dispProperties(true); } void MainTreeWidget::refreshItem(SvnItemModelNode *node) { if (node) { m_Data->m_Model->refreshItem(node); } } void MainTreeWidget::slotChangeProperties(const svn::PropertiesMap &pm, const QStringList &dellist, const QString &path) { m_Data->m_Model->svnWrapper()->changeProperties(pm, dellist, path); SvnItemModelNode *which = SelectedNode(); if (which && which->fullName() == path) { m_Data->m_Model->refreshItem(which); dispProperties(true); } } void MainTreeWidget::dispProperties(bool force) { CursorStack a(Qt::BusyCursor); bool cache_Only = (!force && isNetworked() && !Kdesvnsettings::properties_on_remote_items()); svn::PathPropertiesMapListPtr pm; SvnItem *k = Selected(); if (!k || !k->isRealVersioned()) { emit sigProplist(svn::PathPropertiesMapListPtr(), false, false, QString("")); return; } svn::Revision rev(isWorkingCopy() ? svn::Revision::WORKING : baseRevision()); pm = m_Data->m_Model->svnWrapper()->propList(k->fullName(), rev, cache_Only); emit sigProplist(pm, isWorkingCopy(), k->isDir(), k->fullName()); } void MainTreeWidget::slotCat() { SvnItem *k = Selected(); if (!k) { return; } m_Data->m_Model->svnWrapper()->slotMakeCat(isWorkingCopy() ? svn::Revision::HEAD : baseRevision(), k->fullName(), k->shortName(), - isWorkingCopy() ? svn::Revision::HEAD : baseRevision(), 0); + isWorkingCopy() ? svn::Revision::HEAD : baseRevision(), nullptr); } void MainTreeWidget::slotRevisionCat() { SvnItem *k = Selected(); if (!k) { return; } Rangeinput_impl::revision_range range; if (Rangeinput_impl::getRevisionRange(range, true, true)) { - m_Data->m_Model->svnWrapper()->slotMakeCat(range.first, k->fullName(), k->shortName(), isWorkingCopy() ? svn::Revision::WORKING : baseRevision(), 0); + m_Data->m_Model->svnWrapper()->slotMakeCat(range.first, k->fullName(), k->shortName(), isWorkingCopy() ? svn::Revision::WORKING : baseRevision(), nullptr); } } void MainTreeWidget::slotResolved() { if (!isWorkingCopy()) { return; } SvnItem *which = SelectedOrMain(); if (!which) { return; } m_Data->m_Model->svnWrapper()->slotResolved(which->fullName()); which->refreshStatus(true); //slotRescanIcons(false); } void MainTreeWidget::slotTryResolve() { if (!isWorkingCopy()) { return; } SvnItem *which = Selected(); if (!which || which->isDir()) { return; } m_Data->m_Model->svnWrapper()->slotResolve(which->fullName()); } void MainTreeWidget::slotLeftDelete() { makeDelete(DirSelectionList()); } void MainTreeWidget::slotDelete() { makeDelete(SelectionList()); } void MainTreeWidget::makeDelete(const SvnItemList &lst) { if (lst.isEmpty()) { KMessageBox::error(this, i18n("Nothing selected for delete")); return; } svn::Paths items; QStringList displist; QList kioList; SvnItemList::const_iterator liter; for (liter = lst.begin(); liter != lst.end(); ++liter) { if (!(*liter)->isRealVersioned()) { QUrl _uri(QUrl::fromLocalFile((*liter)->fullName())); kioList.append(_uri); } else { items.push_back((*liter)->fullName()); } displist.append((*liter)->fullName()); } QPointer dlg(new DeleteForm(displist, QApplication::activeModalWidget())); dlg->showExtraButtons(isWorkingCopy() && !items.isEmpty()); if (dlg->exec() == QDialog::Accepted) { bool force = dlg->force_delete(); bool keep = dlg->keep_local(); WidgetBlockStack st(this); if (!kioList.isEmpty()) { KIO::Job *aJob = KIO::del(kioList); if (!aJob->exec()) { KJobWidgets::setWindow(aJob, this); aJob->uiDelegate()->showErrorMessage(); delete dlg; return; } } if (!items.isEmpty()) { m_Data->m_Model->svnWrapper()->makeDelete(svn::Targets(items), keep, force); } refreshCurrentTree(); } delete dlg; } void MainTreeWidget::internalDrop(const QList &_lst, Qt::DropAction action, const QModelIndex &index) { if (_lst.isEmpty()) { return; } QList lst = _lst; QString target; QString nProto; if (!isWorkingCopy()) { nProto = svn::Url::transformProtokoll(lst[0].scheme()); } QList::iterator it = lst.begin(); for (; it != lst.end(); ++it) { (*it).setQuery(QUrlQuery()); if (!nProto.isEmpty()) (*it).setScheme(nProto); } if (index.isValid()) { SvnItemModelNode *node = static_cast(index.internalPointer()); target = node->fullName(); } else { target = baseUri(); } if (action == Qt::MoveAction) { m_Data->m_Model->svnWrapper()->makeMove(lst, target); } else if (action == Qt::CopyAction) { m_Data->m_Model->svnWrapper()->makeCopy(lst, target, (isWorkingCopy() ? svn::Revision::UNDEFINED : baseRevision())); } refreshCurrentTree(); } void MainTreeWidget::slotUrlDropped(const QList &_lst, Qt::DropAction action, const QModelIndex &index, bool intern) { if (_lst.isEmpty()) { return; } if (intern) { internalDrop(_lst, action, index); return; } QUrl target; if (index.isValid()) { SvnItemModelNode *node = static_cast(index.internalPointer()); target = node->Url(); } else { target = baseUriAsUrl(); } if (baseUri().isEmpty()) { openUrl(_lst[0]); return; } QString path = _lst[0].path(); QFileInfo fi(path); if (!isWorkingCopy()) { if (!fi.isDir()) { target.setPath(target.path() + QLatin1Char('/') + _lst[0].fileName()); } slotImportIntoDir(_lst[0].toLocalFile(), target, fi.isDir()); } else { WidgetBlockStack w(this); KIO::Job *job = KIO::copy(_lst, target); connect(job, SIGNAL(result(KJob*)), SLOT(slotCopyFinished(KJob*))); job->exec(); } } void MainTreeWidget::slotCopyFinished(KJob *_job) { KIO::CopyJob *job = dynamic_cast(_job); if (!job) { return; } bool ok = true; if (job->error()) { KJobWidgets::setWindow(job, this); job->uiDelegate()->showErrorMessage(); ok = false; } if (ok) { const QList lst = job->srcUrls(); const QString base = job->destUrl().toLocalFile() + QLatin1Char('/'); svn::Paths tmp; tmp.reserve(lst.size()); Q_FOREACH(const QUrl &url, lst) { tmp.push_back(svn::Path(base + url.fileName())); } m_Data->m_Model->svnWrapper()->addItems(tmp, svn::DepthInfinity); } refreshCurrentTree(); } void MainTreeWidget::stopLogCache() { QAction *temp = filesActions()->action(QStringLiteral("update_log_cache")); m_Data->m_Model->svnWrapper()->stopFillCache(); if (temp) { temp->setText(i18n("Update log cache")); } } void MainTreeWidget::slotUpdateLogCache() { if (baseUri().length() > 0 && m_Data->m_Model->svnWrapper()->doNetworking()) { QAction *temp = filesActions()->action(QStringLiteral("update_log_cache")); if (!m_Data->m_Model->svnWrapper()->threadRunning(SvnActions::fillcachethread)) { m_Data->m_Model->svnWrapper()->startFillCache(baseUri()); if (temp) { temp->setText(i18n("Stop updating the log cache")); } } else { m_Data->m_Model->svnWrapper()->stopFillCache(); if (temp) { temp->setText(i18n("Update log cache")); } } } } void MainTreeWidget::slotMkBaseDirs() { bool isopen = !baseUri().isEmpty(); if (!isopen) { return; } QString parentDir = baseUri(); svn::Paths targets; targets.append(svn::Path(parentDir + QLatin1String("/trunk"))); targets.append(svn::Path(parentDir + QLatin1String("/branches"))); targets.append(svn::Path(parentDir + QLatin1String("/tags"))); QString msg = i18n("Automatic generated base layout by kdesvn"); isopen = m_Data->m_Model->svnWrapper()->makeMkdir(svn::Targets(targets), msg); if (isopen) { refreshCurrentTree(); } } void MainTreeWidget::slotMkdir() { SvnItemModelNode *k = SelectedNode(); QString parentDir; if (k) { if (!k->isDir()) { - KMessageBox::sorry(0, i18n("May not make subdirectories of a file")); + KMessageBox::sorry(nullptr, i18n("May not make subdirectories of a file")); return; } parentDir = k->fullName(); } else { parentDir = baseUri(); } QString ex = m_Data->m_Model->svnWrapper()->makeMkdir(parentDir); if (!ex.isEmpty()) { m_Data->m_Model->refreshDirnode(static_cast(k), true, true); } } void MainTreeWidget::slotRename() { copy_move(true); } void MainTreeWidget::slotCopy() { copy_move(false); } void MainTreeWidget::copy_move(bool move) { if (isWorkingCopy() && SelectedNode() == m_Data->m_Model->firstRootChild()) { return; } bool ok; SvnItemModelNode *which = SelectedNode(); if (!which) { return; } QString nName = CopyMoveView_impl::getMoveCopyTo(&ok, move, which->fullName(), baseUri(), this); if (!ok) { return; } if (move) { m_Data->m_Model->svnWrapper()->makeMove(which->fullName(), nName); } else { m_Data->m_Model->svnWrapper()->makeCopy(which->fullName(), nName, isWorkingCopy() ? svn::Revision::HEAD : baseRevision()); } } void MainTreeWidget::slotCleanupAction() { if (!isWorkingCopy()) { return; } SvnItemModelNode *which = SelectedNode(); if (!which) { which = m_Data->m_Model->firstRootChild(); } if (!which || !which->isDir()) { return; } if (m_Data->m_Model->svnWrapper()->makeCleanup(which->fullName())) { which->refreshStatus(true); } } void MainTreeWidget::slotMergeRevisions() { if (!isWorkingCopy()) { return; } SvnItemModelNode *which = SelectedNode(); if (!which) { return; } bool force, dry, rec, irelated, useExternal, allowmixedrevs; Rangeinput_impl::revision_range range; if (!MergeDlg_impl::getMergeRange(range, &force, &rec, &irelated, &dry, &useExternal, &allowmixedrevs, this)) { return; } if (!useExternal) { m_Data->m_Model->svnWrapper()->slotMergeWcRevisions(which->fullName(), range.first, range.second, rec, !irelated, force, dry, allowmixedrevs); } else { m_Data->m_Model->svnWrapper()->slotMergeExternal(which->fullName(), which->fullName(), which->fullName(), range.first, range.second, isWorkingCopy() ? svn::Revision::UNDEFINED : m_Data->m_remoteRevision, rec); } refreshItem(which); if (which->isDir()) { m_Data->m_Model->refreshDirnode(static_cast(which), true, false); } } void MainTreeWidget::slotMerge() { SvnItemModelNode *which = SelectedNode(); QString src1, src2, target; if (isWorkingCopy()) { if (m_Data->merge_Target.isEmpty()) { target = which ? which->fullName() : baseUri(); } else { target = m_Data->merge_Target; } src1 = m_Data->merge_Src1; } else { if (m_Data->merge_Src1.isEmpty()) { src1 = which ? which->fullName() : baseUri(); } else { src1 = m_Data->merge_Src1; } target = m_Data->merge_Target; } src2 = m_Data->merge_Src2; QPointer dlg(new KSvnSimpleOkDialog(QStringLiteral("merge_dialog"))); dlg->setWindowTitle(i18nc("@title:window", "Merge")); dlg->setWithCancelButton(); dlg->setHelp(QLatin1String("merging-items")); MergeDlg_impl *ptr(new MergeDlg_impl(dlg)); ptr->setDest(target); ptr->setSrc1(src1); ptr->setSrc2(src1); dlg->addWidget(ptr); if (dlg->exec() == QDialog::Accepted) { src1 = ptr->Src1(); src2 = ptr->Src2(); if (src2.isEmpty()) { src2 = src1; } target = ptr->Dest(); m_Data->merge_Src2 = src2; m_Data->merge_Src1 = src1; m_Data->merge_Target = target; bool force = ptr->force(); bool dry = ptr->dryrun(); bool rec = ptr->recursive(); bool irelated = ptr->ignorerelated(); bool useExternal = ptr->useExtern(); bool allowmixedrevs = ptr->allowmixedrevs(); bool recordOnly = ptr->recordOnly(); Rangeinput_impl::revision_range range = ptr->getRange(); bool reintegrate = ptr->reintegrate(); if (!useExternal) { m_Data->m_Model->svnWrapper()->slotMerge(src1, src2, target, range.first, range.second, isWorkingCopy() ? svn::Revision::UNDEFINED : m_Data->m_remoteRevision, rec, !irelated, force, dry, recordOnly, reintegrate, allowmixedrevs); } else { m_Data->m_Model->svnWrapper()->slotMergeExternal(src1, src2, target, range.first, range.second, isWorkingCopy() ? svn::Revision::UNDEFINED : m_Data->m_remoteRevision, rec); } if (isWorkingCopy()) { // refreshItem(which); // refreshRecursive(which); refreshCurrentTree(); } } delete dlg; enableActions(); } void MainTreeWidget::slotRelocate() { if (!isWorkingCopy()) { return; } SvnItem *k = SelectedOrMain(); if (!k) { - KMessageBox::error(0, i18n("Error getting entry to relocate")); + KMessageBox::error(nullptr, i18n("Error getting entry to relocate")); return; } const QString path = k->fullName(); const QUrl fromUrl = k->Url(); QPointer dlg(new KSvnSimpleOkDialog(QStringLiteral("relocate_dlg"))); dlg->setWindowTitle(i18nc("@title:window", "Relocate Path %1", path)); dlg->setWithCancelButton(); CheckoutInfo_impl *ptr(new CheckoutInfo_impl(dlg)); ptr->setStartUrl(fromUrl); ptr->disableAppend(true); ptr->disableTargetDir(true); ptr->disableRange(true); ptr->disableOpen(true); ptr->hideDepth(true); ptr->hideOverwrite(true); dlg->addWidget(ptr); bool done = false; if (dlg->exec() == QDialog::Accepted) { if (!ptr->reposURL().isValid()) { KMessageBox::error(QApplication::activeModalWidget(), i18n("Invalid url given!"), i18n("Relocate path %1", path)); delete dlg; return; } done = m_Data->m_Model->svnWrapper()->makeRelocate(fromUrl, ptr->reposURL(), path, ptr->overwrite(), ptr->ignoreExternals()); } delete dlg; if (done) { refreshItem(k->sItem()); } } void MainTreeWidget::slotImportDirsIntoCurrent() { slotImportIntoCurrent(true); } /*! \fn MainTreeWidget::slotImportIntoCurrent() */ void MainTreeWidget::slotImportIntoCurrent(bool dirs) { if (selectionCount() > 1) { KMessageBox::error(this, i18n("Cannot import into multiple targets")); return; } QUrl targetDir; if (selectionCount() == 0) { if (isNetworked()) targetDir = QUrl(baseUri()); else targetDir = QUrl::fromLocalFile(baseUri()); } else { targetDir = SelectedNode()->Url(); } QString source; if (dirs) { source = QFileDialog::getExistingDirectory(this, i18n("Import files from folder")); } else { source = QFileDialog::getOpenFileName(this, i18n("Import file"), QString()); } slotImportIntoDir(source, targetDir, dirs); } void MainTreeWidget::slotImportIntoDir(const QString &source, const QUrl &_targetUri, bool dirs) { QString sourceUri = source; while (sourceUri.endsWith(QLatin1Char('/'))) { sourceUri.chop(1); } if (sourceUri.isEmpty()) { return; } if (_targetUri.isEmpty()) { return; } QUrl targetUri(_targetUri); QPointer dlg(new KSvnSimpleOkDialog(QStringLiteral("import_log_msg"))); dlg->setWindowTitle(i18nc("@title:window", "Import Log")); dlg->setWithCancelButton(); Commitmsg_impl *ptr = nullptr; Importdir_logmsg *ptr2 = nullptr; if (dirs) { ptr2 = new Importdir_logmsg(dlg); ptr2->createDirboxDir(QLatin1Char('"') + QFileInfo(sourceUri).fileName() + QLatin1Char('"')); ptr = ptr2; } else { ptr = new Commitmsg_impl(dlg); } ptr->initHistory(); dlg->addWidget(ptr); if (dlg->exec() != QDialog::Accepted) { if (dlg) { ptr->saveHistory(true); delete dlg; } return; } QString logMessage = ptr->getMessage(); svn::Depth rec = ptr->getDepth(); ptr->saveHistory(false); if (dirs && ptr2 && ptr2->createDir()) { targetUri.setPath(targetUri.path() + QLatin1Char('/') + QFileInfo(sourceUri).fileName()); } if (ptr2) { m_Data->m_Model->svnWrapper()->slotImport(sourceUri, targetUri, logMessage, rec, ptr2->noIgnore(), ptr2->ignoreUnknownNodes()); } else { m_Data->m_Model->svnWrapper()->slotImport(sourceUri, targetUri, logMessage, rec, false, false); } if (!isWorkingCopy()) { if (selectionCount() == 0) { refreshCurrentTree(); } else { m_Data->m_Model->refreshItem(SelectedNode()); } } delete dlg; } void MainTreeWidget::slotChangeToRepository() { if (!isWorkingCopy()) { return; } SvnItemModelNode *k = m_Data->m_Model->firstRootChild(); /* huh... */ if (!k) { return; } svn::InfoEntry i; if (!m_Data->m_Model->svnWrapper()->singleInfo(k->Url().toString(), svn::Revision::UNDEFINED, i)) { return; } if (i.reposRoot().isEmpty()) { KMessageBox::sorry(QApplication::activeModalWidget(), i18n("Could not retrieve repository of working copy."), i18n("SVN Error")); } else { sigSwitchUrl(i.reposRoot()); } } void MainTreeWidget::slotCheckNewItems() { if (!isWorkingCopy()) { - KMessageBox::sorry(0, i18n("Only in working copy possible."), i18n("Error")); + KMessageBox::sorry(nullptr, i18n("Only in working copy possible."), i18n("Error")); return; } if (selectionCount() > 1) { - KMessageBox::sorry(0, i18n("Only on single folder possible"), i18n("Error")); + KMessageBox::sorry(nullptr, i18n("Only on single folder possible"), i18n("Error")); return; } SvnItem *w = SelectedOrMain(); if (!w) { - KMessageBox::sorry(0, i18n("Sorry - internal error"), i18n("Error")); + KMessageBox::sorry(nullptr, i18n("Sorry - internal error"), i18n("Error")); return; } m_Data->m_Model->svnWrapper()->checkAddItems(w->fullName(), true); } void MainTreeWidget::refreshCurrent(SvnItem *cur) { if (!cur || !cur->sItem()) { refreshCurrentTree(); return; } QCoreApplication::processEvents(); setUpdatesEnabled(false); if (cur->isDir()) { m_Data->m_Model->refreshDirnode(static_cast(cur->sItem())); } else { m_Data->m_Model->refreshItem(cur->sItem()); } setUpdatesEnabled(true); m_TreeView->viewport()->repaint(); } void MainTreeWidget::slotReinitItem(SvnItem *item) { if (!item) { return; } SvnItemModelNode *k = item->sItem(); if (!k) { return; } m_Data->m_Model->refreshItem(k); if (k->isDir()) { m_Data->m_Model->clearNodeDir(static_cast(k)); } } void MainTreeWidget::keyPressEvent(QKeyEvent *event) { if ((event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) && !event->isAutoRepeat()) { QModelIndex index = SelectedIndex(); if (index.isValid()) { itemActivated(index, true); return; } } QWidget::keyPressEvent(event); } void MainTreeWidget::slotItemExpanded(const QModelIndex &) { } void MainTreeWidget::slotItemsInserted(const QModelIndex &) { m_Data->m_resizeColumnsTimer.start(50); } void MainTreeWidget::slotDirSelectionChanged(const QItemSelection &_item, const QItemSelection &) { const QModelIndexList _indexes = _item.indexes(); switch (DirselectionCount()) { case 1: m_DirTreeView->setStatusTip(i18n("Hold Ctrl key while click on selected item for unselect")); break; case 2: m_DirTreeView->setStatusTip(i18n("See context menu for more actions")); break; case 0: m_DirTreeView->setStatusTip(i18n("Click for navigate")); break; default: m_DirTreeView->setStatusTip(i18n("Navigation")); break; } if (_indexes.size() >= 1) { const QModelIndex _t = m_Data->srcDirInd(_indexes.at(0)); if (m_Data->m_Model->canFetchMore(_t)) { WidgetBlockStack st(m_TreeView); WidgetBlockStack st2(m_DirTreeView); m_Data->m_Model->fetchMore(_t); } if (Kdesvnsettings::show_navigation_panel()) { m_TreeView->setRootIndex(m_Data->m_SortModel->mapFromSource(_t)); } } else { checkSyncTreeModel(); } if (m_TreeView->selectionModel()->hasSelection()) { m_TreeView->selectionModel()->clearSelection(); } else { enableActions(); } resizeAllColumns(); } void MainTreeWidget::checkSyncTreeModel() { // make sure that the treeview shows the contents of the selected directory in the directory tree view // it can go out of sync when the dir tree model has no current index - then we use the first entry // or when the filter settings are changed QModelIndex curIdxDir = m_DirTreeView->currentIndex(); if (!curIdxDir.isValid() && m_Data->m_DirSortModel->columnCount() > 0) { m_DirTreeView->setCurrentIndex(m_Data->m_DirSortModel->index(0, 0)); curIdxDir = m_DirTreeView->currentIndex(); } const QModelIndex curIdxBase = m_Data->srcDirInd(curIdxDir); m_TreeView->setRootIndex(m_Data->m_SortModel->mapFromSource(curIdxBase)); } void MainTreeWidget::slotCommit() { m_Data->m_Model->svnWrapper()->doCommit(SelectionList()); } void MainTreeWidget::slotDirCommit() { m_Data->m_Model->svnWrapper()->doCommit(DirSelectionList()); } void MainTreeWidget::slotDirUpdate() { const SvnItemList which = DirSelectionList(); svn::Paths what; if (which.isEmpty()) { what.append(svn::Path(baseUri())); } else { what.reserve(which.size()); Q_FOREACH(const SvnItem *item, which) { what.append(svn::Path(item->fullName())); } } m_Data->m_Model->svnWrapper()->makeUpdate(svn::Targets(what), svn::Revision::HEAD, svn::DepthUnknown); } void MainTreeWidget::slotRescanIcons() { m_Data->m_Model->refreshIndex(m_Data->m_Model->firstRootIndex()); } void MainTreeWidget::checkUseNavigation(bool startup) { bool use = Kdesvnsettings::show_navigation_panel(); if (use) { checkSyncTreeModel(); } else { // tree view is the only visible view, make sure to display all m_TreeView->setRootIndex(QModelIndex()); m_TreeView->expand(QModelIndex()); } m_TreeView->setExpandsOnDoubleClick(!use); m_TreeView->setRootIsDecorated(!use); m_TreeView->setItemsExpandable(!use); QList si; if (use) { if (!startup) { si = m_ViewSplitter->sizes(); if (si.size() == 2 && si[0] < 5) { si[0] = 200; m_ViewSplitter->setSizes(si); } } } else { si << 0 << 300; m_ViewSplitter->setSizes(si); } } void MainTreeWidget::slotRepositorySettings() { if (baseUri().length() == 0) { return; } svn::InfoEntry inf; if (!m_Data->m_Model->svnWrapper()->singleInfo(baseUri(), baseRevision(), inf)) { return; } if (inf.reposRoot().isEmpty()) { KMessageBox::sorry(QApplication::activeModalWidget(), i18n("Could not retrieve repository."), i18n("SVN Error")); } else { DbSettings::showSettings(inf.reposRoot().toString(), this); } } void MainTreeWidget::slotRightProperties() { SvnItem *k = Selected(); if (!k) { return; } m_Data->m_Model->svnWrapper()->editProperties(k, isWorkingCopy() ? svn::Revision::WORKING : svn::Revision::HEAD); } void MainTreeWidget::slotLeftProperties() { SvnItem *k = DirSelected(); if (!k) { return; } m_Data->m_Model->svnWrapper()->editProperties(k, isWorkingCopy() ? svn::Revision::WORKING : svn::Revision::HEAD); } void MainTreeWidget::slotDirRecProperty() { SvnItem *k = DirSelected(); if (!k) { return; } KMessageBox::information(this, i18n("Not yet implemented"), i18n("Edit property recursively")); } diff --git a/src/svnfrontend/maintreewidget.h b/src/svnfrontend/maintreewidget.h index 0b16ad40..60b21281 100644 --- a/src/svnfrontend/maintreewidget.h +++ b/src/svnfrontend/maintreewidget.h @@ -1,200 +1,200 @@ /*************************************************************************** * Copyright (C) 2008 by Rajko Albrecht ral@alwins-world.de * * http://kdesvn.alwins-world.de/ * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef MAINTREEWIDGET_H #define MAINTREEWIDGET_H #include "ui_treeWidget.h" #include "itemdisplay.h" #include "frontendtypes.h" #include "svnqt/status.h" #include "svnqt/client.h" #include #include class KActionCollection; class MainTreeWidgetData; class SvnItemModelNode; class KJob; class MainTreeWidget: public QWidget, public Ui::mainTreeWidget, public ItemDisplay { Q_OBJECT public: - explicit MainTreeWidget(KActionCollection *aCollection, QWidget *parent = 0, Qt::WindowFlags f = 0); + explicit MainTreeWidget(KActionCollection *aCollection, QWidget *parent = nullptr, Qt::WindowFlags f = nullptr); virtual ~MainTreeWidget(); virtual QWidget *realWidget(); virtual SvnItem *Selected()const; virtual SvnItemList SelectionList()const; virtual svn::Revision baseRevision()const; virtual bool openUrl(const QUrl &url, bool noReinit = false); virtual SvnItem *SelectedOrMain()const; SvnItem *DirSelected()const; QModelIndex SelectedIndex()const; QModelIndex DirSelectedIndex()const; SvnItemModelNode *SelectedNode()const; SvnItemModelNode *DirSelectedNode()const; SvnItemList DirSelectionList()const; SvnItem *DirSelectedOrMain()const; void refreshItem(SvnItemModelNode *node); void clear(); KActionCollection *filesActions(); Q_SIGNALS: void sigLogMessage(const QString &); void sigExtraStatusMessage(const QString &); void changeCaption(const QString &); void sigShowPopup(const QString &, QWidget **); void sigUrlOpend(bool); void sigSwitchUrl(const QUrl &); void sigUrlChanged(const QUrl &); void sigProplist(const svn::PathPropertiesMapListPtr &, bool, bool, const QString &); void sigListError(); void sigCacheStatus(qlonglong, qlonglong); public Q_SLOTS: void closeMe(); void refreshCurrentTree(); void slotSettingsChanged(); void slotSelectionChanged(const QItemSelection &, const QItemSelection &); void slotNotifyMessage(const QString &); void slotMkBaseDirs(); void slotMkdir(); void refreshCurrent(SvnItem *); void slotReinitItem(SvnItem *); void stopLogCache(); protected Q_SLOTS: void slotCacheDataChanged(); void slotItemActivated(const QModelIndex &); void slotItemExpanded(const QModelIndex &); void slotItemsInserted(const QModelIndex &); void slotRescanIcons(); void _propListTimeout(); void slotCheckUpdates(); void slotCheckModified(); void readSupportData(); void slotClientException(const QString &); void slotIgnore(); void slotLeftRecAddIgnore(); void slotRightRecAddIgnore(); void slotMakeLog()const; void slotMakeLogNoFollow()const; void slotDirMakeLogNoFollow()const; void slotMakeTree(); void slotMakePartTree(); void slotSelectBrowsingRevision(); void slotLock(); void slotUnlock(); void slotDisplayLastDiff(); void slotSimpleHeadDiff(); void slotSimpleBaseDiff(); void slotDirSimpleBaseDiff(); void slotDiffRevisions(); void slotDiffPathes(); void slotInfo(); void slotBlame(); void slotRangeBlame(); void slotDisplayProperties(); void slotChangeProperties(const svn::PropertiesMap &, const QStringList &, const QString &); void slotCat(); void slotRevisionCat(); void slotResolved(); void slotTryResolve(); void slotDelete(); void slotLeftDelete(); void slotRename(); void slotCopy(); void slotCleanupAction(); void slotMergeRevisions(); void slotMerge(); void slotRelocate(); void slotImportIntoCurrent(bool); void slotImportDirsIntoCurrent(); void slotImportIntoDir(const QString &source, const QUrl &_targetUri, bool dirs); void slotChangeToRepository(); void slotCheckNewItems(); void slotCommit(); void slotDirCommit(); void slotDirUpdate(); void slotDirRecProperty(); void slotDirSelectionChanged(const QItemSelection &_item, const QItemSelection &); void checkSyncTreeModel(); void _openUrl(const QUrl &); void enableActions(); void slotUnfoldTree(); void slotFoldTree(); void slotOpenWith(); void slotContextMenu(const QPoint &); void slotDirContextMenu(const QPoint &); void slotCopyFinished(KJob *job); void slotUpdateLogCache(); void slotUrlDropped(const QList &, Qt::DropAction, const QModelIndex &, bool); void slotRepositorySettings(); void slotRightProperties(); void slotLeftProperties(); void resizeAllColumns(); protected: virtual void keyPressEvent(QKeyEvent *); void setupActions(); bool uniqueTypeSelected(); KService::List offersList(SvnItem *item, bool execOnly = false)const; int selectionCount()const; int DirselectionCount()const; void dispProperties(bool); void copy_move(bool move); void itemActivated(const QModelIndex &index, bool keypress = false); void internalDrop(const QList &_lst, Qt::DropAction action, const QModelIndex &index); void execContextMenu(const SvnItemList &); void simpleWcDiff(SvnItem *which, const svn::Revision &, const svn::Revision &); void doLog(bool, bool)const; void checkUseNavigation(bool startup = false); void makeDelete(const SvnItemList &lst); void recAddIgnore(SvnItem *which); private: MainTreeWidgetData *m_Data; void enableAction(const QString &, bool); QAction *add_action(const QString &actionname, const QString &text, const QKeySequence &sequ, const QIcon &, QObject *, const char *slot); }; #endif diff --git a/src/svnfrontend/mergedlg_impl.h b/src/svnfrontend/mergedlg_impl.h index cb4a293f..8de1676c 100644 --- a/src/svnfrontend/mergedlg_impl.h +++ b/src/svnfrontend/mergedlg_impl.h @@ -1,69 +1,69 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef MERGEDLG_IMPL_H #define MERGEDLG_IMPL_H #include "ui_merge_dlg.h" #include "rangeinput_impl.h" namespace svn { class MergeParameter; } class MergeDlg_impl: public QWidget, public Ui::MergeDlg { Q_OBJECT public: - explicit MergeDlg_impl(QWidget *parent = 0, bool src1 = true, bool src2 = true, bool out = true, bool record_only = true, bool reintegrate = true); + explicit MergeDlg_impl(QWidget *parent = nullptr, bool src1 = true, bool src2 = true, bool out = true, bool record_only = true, bool reintegrate = true); virtual ~MergeDlg_impl(); bool recursive()const; bool force()const; bool ignorerelated()const; bool dryrun()const; bool useExtern()const; bool recordOnly()const; bool reintegrate()const; bool allowmixedrevs()const; QString Src1()const; QString Src2()const; QString Dest()const; Rangeinput_impl::revision_range getRange()const; void setSrc1(const QString &); void setSrc2(const QString &); void setDest(const QString &); //! simple caller /*! * This simplyfies the call if only some revision into a working copy should merged. */ static bool getMergeRange(Rangeinput_impl::revision_range &range, - bool *force, bool *recursive, bool *ignorerelated, bool *dry, bool *useExternal, bool *allowmixedrevs, QWidget *parent = 0); + bool *force, bool *recursive, bool *ignorerelated, bool *dry, bool *useExternal, bool *allowmixedrevs, QWidget *parent = nullptr); protected Q_SLOTS: virtual void externDisplayToggled(bool); virtual void recordOnlyToggled(bool); virtual void reintegrateToggled(bool); }; #endif diff --git a/src/svnfrontend/models/svndirsortfilter.h b/src/svnfrontend/models/svndirsortfilter.h index 16baad8e..7b604b96 100644 --- a/src/svnfrontend/models/svndirsortfilter.h +++ b/src/svnfrontend/models/svndirsortfilter.h @@ -1,34 +1,34 @@ /*************************************************************************** * Copyright (C) 2008 by Rajko Albrecht ral@alwins-world.de * * http://kdesvn.alwins-world.de/ * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef SVNDIRSORTFILTER_H #define SVNDIRSORTFILTER_H #include "svnsortfilter.h" class SvnDirSortFilterProxy final : public SvnSortFilterProxy { Q_OBJECT public: - explicit SvnDirSortFilterProxy(QObject *parent = 0); + explicit SvnDirSortFilterProxy(QObject *parent = nullptr); int columnCount(const QModelIndex &parent = QModelIndex()) const override; }; #endif diff --git a/src/svnfrontend/models/svnitemmodel.cpp b/src/svnfrontend/models/svnitemmodel.cpp index 4be74846..19a4d091 100644 --- a/src/svnfrontend/models/svnitemmodel.cpp +++ b/src/svnfrontend/models/svnitemmodel.cpp @@ -1,921 +1,921 @@ /*************************************************************************** * Copyright (C) 2008 by Rajko Albrecht ral@alwins-world.de * * http://kdesvn.alwins-world.de/ * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "svnitemmodel.h" #include "svnitemnode.h" #include "svnactions.h" #include "getinfothread.h" #include "svnfrontend/maintreewidget.h" #include "settings/kdesvnsettings.h" #include "helpers/kdesvn_debug.h" #include "svnqt/status.h" #include "svnqt/client.h" #include "svnqt/path.h" #include "svnqt/svnqt_defines.h" #include #include #include #include #include #include #include #include #include /***************************** * Internal data class begin * *****************************/ class SvnItemModelData { SvnItemModelData(const SvnItemModelData &); SvnItemModelData &operator=(const SvnItemModelData &); public: SvnItemModelData(SvnItemModel *aCb, MainTreeWidget *display) - : m_rootNode(0), m_SvnActions(NULL), m_Cb(aCb), m_Display(display), m_DirWatch(NULL) + : m_rootNode(nullptr), m_SvnActions(nullptr), m_Cb(aCb), m_Display(display), m_DirWatch(nullptr) { m_Uid = QUuid::createUuid().toString(); m_InfoThread = new GetInfoThread(aCb); } ~SvnItemModelData() { m_InfoThread->cancelMe(); if (!m_InfoThread->wait(500)) { m_InfoThread->terminate(); } delete m_InfoThread; delete m_rootNode; delete m_DirWatch; - m_rootNode = 0; + m_rootNode = nullptr; } void clear() { delete m_rootNode; delete m_DirWatch; - m_DirWatch = 0; + m_DirWatch = nullptr; m_rootNode = new SvnItemModelNodeDir(m_SvnActions, m_Display); } SvnItemModelNode *nodeForIndex(const QModelIndex &index)const { return index.isValid() ? static_cast(index.internalPointer()) : m_rootNode; } QModelIndex indexForNode(SvnItemModelNode *node, int rowNumber = -1)const { if (!node || node == m_rootNode) { return QModelIndex(); } return m_Cb->createIndex(rowNumber == -1 ? node->rowNumber() : rowNumber, 0, node); } bool isRemoteAdded(const svn::Status &_Stat)const { return m_SvnActions->isUpdated(_Stat.path()) && _Stat.validReposStatus() && !_Stat.validLocalStatus(); } bool MustCreateDir(const svn::Status &_Stat)const { // keep in sync with SvnItem::isDir() if (_Stat.entry().isValid() || isRemoteAdded(_Stat)) { if (_Stat.entry().kind() != svn_node_unknown) { return _Stat.entry().kind() == svn_node_dir; } } /* must be a local file */ QFileInfo f(_Stat.path()); return f.isDir(); } void addWatchFile(const QString &aFile) { if (m_DirWatch) { m_DirWatch->addFile(aFile); } } void addWatchDir(const QString &aDir) { if (m_DirWatch) { m_DirWatch->addDir(aDir); } } SvnItemModelNodeDir *m_rootNode; SvnActions *m_SvnActions; SvnItemModel *m_Cb; MainTreeWidget *m_Display; KDirWatch *m_DirWatch; QString m_Uid; mutable GetInfoThread *m_InfoThread; }; /***************************** * Internal data class end * *****************************/ SvnItemModel::SvnItemModel(MainTreeWidget *display, QObject *parent) : QAbstractItemModel(parent), m_Data(new SvnItemModelData(this, display)) { m_Data->m_SvnActions = new SvnActions(display); m_Data->m_rootNode = new SvnItemModelNodeDir(m_Data->m_SvnActions, display); } SvnItemModel::~SvnItemModel() { } SvnItemModelNode *SvnItemModel::firstRootChild() { if (!m_Data->m_rootNode) { - return 0; + return nullptr; } return m_Data->m_rootNode->child(0); } QModelIndex SvnItemModel::firstRootIndex() { return m_Data->indexForNode(firstRootChild()); } SvnItemModelNode *SvnItemModel::nodeForIndex(const QModelIndex &index) { return m_Data->nodeForIndex(index); } void SvnItemModel::setRootNodeStat(const svn::StatusPtr &stat) { m_Data->m_rootNode->setStat(stat); } void SvnItemModel::clear() { int numRows = m_Data->m_rootNode->childList().count(); beginRemoveRows(QModelIndex(), 0, numRows); m_Data->clear(); endRemoveRows(); } void SvnItemModel::beginRemoveRows(const QModelIndex &parent, int first, int last) { m_Data->m_InfoThread->clearNodes(); m_Data->m_InfoThread->cancelMe(); if (!m_Data->m_InfoThread->wait(1000)) { } QAbstractItemModel::beginRemoveRows(parent, first, last); } void SvnItemModel::clearNodeDir(SvnItemModelNodeDir *node) { QModelIndex ind = m_Data->indexForNode(node); if (!node) { node = m_Data->m_rootNode; } int numRows = node->childList().size(); beginRemoveRows(ind, 0, numRows); node->clear(); endRemoveRows(); } bool SvnItemModel::hasChildren(const QModelIndex &parent)const { if (!parent.isValid()) { return true; } return static_cast(parent.internalPointer())->NodeHasChilds(); } bool SvnItemModel::filterIndex(const QModelIndex &parent, int childRow, svnmodel::ItemTypeFlag showOnly)const { SvnItemModelNode *node = m_Data->nodeForIndex(parent); if (childRow < 0) { return false; } if (!node->NodeIsDir()) { qCDebug(KDESVN_LOG) << "Parent ist kein Dir" << endl; return false; } SvnItemModelNode *child = static_cast(node)->child(childRow); if (child) { if ((child->isDir() && !showOnly.testFlag(svnmodel::Dir)) || (!child->isDir() && !showOnly.testFlag(svnmodel::File))) { return true; } return ItemDisplay::filterOut(child); } return false; } QVariant SvnItemModel::data(const QModelIndex &index, int role)const { SvnItemModelNode *node = m_Data->nodeForIndex(index); switch (role) { case Qt::DisplayRole: case SORT_ROLE: switch (index.column()) { case Name: return node->shortName(); case Status: return node->infoText(); case LastRevision: return QString::number(node->cmtRev()); case LastAuthor: return node->cmtAuthor(); case LastDate: return node->fullDate(); case Locked: return node->lockOwner(); } break; case Qt::DecorationRole: if (index.column() == 0) { int size = Kdesvnsettings::listview_icon_size(); bool overlay = Kdesvnsettings::display_overlays(); return node->getPixmap(size, overlay); } break; case Qt::EditRole: switch (index.column()) { case Name: return node->shortName(); } break; case Qt::BackgroundRole: { QColor cl = node->backgroundColor(); if (cl.isValid()) { return QBrush(cl); } break; } case Qt::ToolTipRole: { switch (index.column()) { case Name: if (node->hasToolTipText()) { return node->getToolTipText(); } else { m_Data->m_InfoThread->appendNode(node); return QVariant(); } } break; } } return QVariant(); } QModelIndex SvnItemModel::index(int row, int column, const QModelIndex &parent)const { SvnItemModelNode *node = m_Data->nodeForIndex(parent); if (row < 0) { return QModelIndex(); } Q_ASSERT(node->NodeIsDir()); SvnItemModelNode *child = static_cast(node)->child(row); if (child) { return createIndex(row, column, child); } else { return QModelIndex(); } } QVariant SvnItemModel::headerData(int section, Qt::Orientation orientation, int role) const { if (orientation == Qt::Vertical) { return QVariant(); } switch (role) { case Qt::DisplayRole: switch (section) { case Name: return (i18n("Name")); case Status: return (i18n("Status")); case LastRevision: return (i18n("Last changed Revision")); case LastAuthor: return (i18n("Last author")); case LastDate: return (i18n("Last change date")); case Locked: return (i18n("Locked by")); } } return QVariant(); } int SvnItemModel::columnCount(const QModelIndex & /*parent*/)const { return ColumnCount; } int SvnItemModel::rowCount(const QModelIndex &parent)const { if (!m_Data || !m_Data->m_rootNode) { return 0; } if (!parent.isValid()) { return m_Data->m_rootNode->childList().count(); } SvnItemModelNodeDir *node = static_cast(m_Data->nodeForIndex(parent)); return node->childList().count(); } QModelIndex SvnItemModel::parent(const QModelIndex &index)const { if (!index.isValid()) { return QModelIndex(); } SvnItemModelNode *child = static_cast(index.internalPointer()); return m_Data->indexForNode(child->parent()); } SvnActions *SvnItemModel::svnWrapper() { return m_Data->m_SvnActions; } int SvnItemModel::checkDirs(const QString &_what, SvnItemModelNode *_parent) { QString what = _what; svn::StatusEntries dlist; while (what.endsWith(QLatin1Char('/'))) { what.chop(1); } // prevent this from checking unversioned folder. FIXME: what happen when we do open url on a non-working-copy folder?? #ifdef DEBUG_TIMER QTime _counttime; _counttime.start(); #endif if (!m_Data->m_Display->isWorkingCopy() || (!_parent) || ((_parent) && (_parent->isVersioned()))) { if (!svnWrapper()->makeStatus(what, dlist, m_Data->m_Display->baseRevision(), false, true, true)) { return -1; } } else { return checkUnversionedDirs(_parent); } #ifdef DEBUG_TIMER qCDebug(KDESVN_LOG) << "Time for getting entries: " << _counttime.elapsed(); _counttime.restart(); #endif svn::StatusEntries neweritems; svnWrapper()->getaddedItems(what, neweritems); dlist += neweritems; svn::StatusEntries::iterator it = dlist.begin(); - SvnItemModelNode *node = 0; + SvnItemModelNode *node = nullptr; for (; it != dlist.end(); ++it) { if ((*it)->path() == what || (*it)->entry().url().toString() == what) { if (!_parent) { // toplevel item beginInsertRows(m_Data->indexForNode(m_Data->m_rootNode), 0, 0); if ((*it)->entry().kind() == svn_node_dir) { node = new SvnItemModelNodeDir(m_Data->m_rootNode, svnWrapper(), m_Data->m_Display); } else { node = new SvnItemModelNode(m_Data->m_rootNode, svnWrapper(), m_Data->m_Display); } node->setStat((*it)); m_Data->m_rootNode->m_Children.prepend(node); endInsertRows(); } dlist.erase(it); break; } } if (_parent) { node = _parent; } #ifdef DEBUG_TIMER qCDebug(KDESVN_LOG) << "Time finding parent node: " << _counttime.elapsed(); #endif insertDirs(node, dlist); return dlist.size(); } void SvnItemModel::insertDirs(SvnItemModelNode *_parent, svn::StatusEntries &dlist) { if (dlist.isEmpty()) { return; } QModelIndex ind = m_Data->indexForNode(_parent); SvnItemModelNodeDir *parent; if (!_parent) { parent = m_Data->m_rootNode; } else { parent = static_cast(_parent); } - SvnItemModelNode *node = 0; + SvnItemModelNode *node = nullptr; beginInsertRows(ind, parent->childList().count(), parent->childList().count() + dlist.count() - 1); svn::StatusEntries::iterator it = dlist.begin(); #ifdef DEBUG_TIMER QTime _counttime; _counttime.start(); #endif for (; it != dlist.end(); ++it) { #ifdef DEBUG_TIMER _counttime.restart(); #endif if (m_Data->MustCreateDir(*(*it))) { node = new SvnItemModelNodeDir(parent, svnWrapper(), m_Data->m_Display); } else { node = new SvnItemModelNode(parent, svnWrapper(), m_Data->m_Display); } node->setStat((*it)); #ifdef DEBUG_TIMER // qCDebug(KDESVN_LOG)<<"Time creating item: "<<_counttime.elapsed(); _counttime.restart(); #endif if (m_Data->m_Display->isWorkingCopy() && m_Data->m_DirWatch) { if (node->isDir()) { m_Data->addWatchDir(node->fullName()); } else { m_Data->addWatchFile(node->fullName()); } } #ifdef DEBUG_TIMER // qCDebug(KDESVN_LOG)<<"Time add watch: "<<_counttime.elapsed(); _counttime.restart(); #endif parent->m_Children.append(node); #ifdef DEBUG_TIMER // qCDebug(KDESVN_LOG)<<"Time append node: "<<_counttime.elapsed(); #endif } #ifdef DEBUG_TIMER _counttime.restart(); #endif endInsertRows(); #ifdef DEBUG_TIMER // qCDebug(KDESVN_LOG)<<"Time append all node: "<<_counttime.elapsed(); #endif } bool SvnItemModel::canFetchMore(const QModelIndex &parent)const { if (!parent.isValid()) { return false; } SvnItemModelNode *node = static_cast(parent.internalPointer()); return node->NodeHasChilds() && static_cast(node)->childList().isEmpty(); } void SvnItemModel::fetchMore(const QModelIndex &parent) { SvnItemModelNode *node = static_cast(parent.internalPointer()); if (!node->isDir()) { return; } if (checkDirs(node->fullName(), node) > 0) { emit itemsFetched(parent); } } bool SvnItemModel::insertRows(int , int, const QModelIndex &) { return false; } bool SvnItemModel::insertColumns(int, int, const QModelIndex &) { return false; } bool SvnItemModel::removeRows(int, int, const QModelIndex &) { return false; } bool SvnItemModel::removeColumns(int, int, const QModelIndex &) { return false; } Qt::ItemFlags SvnItemModel::flags(const QModelIndex &index) const { Qt::ItemFlags f = Qt::ItemIsEnabled | Qt::ItemIsSelectable; if (index.column() == Name) { f |= /*Qt::ItemIsEditable |*/ Qt::ItemIsDragEnabled; } if (!index.isValid()) { f |= Qt::ItemIsDropEnabled; } else { SvnItemModelNode *node = m_Data->nodeForIndex(index); if (node && node->isDir()) { f |= Qt::ItemIsDropEnabled; } } return f; } Qt::DropActions SvnItemModel::supportedDropActions()const { return Qt::CopyAction | Qt::MoveAction; } QStringList SvnItemModel::mimeTypes() const { return QStringList() << QLatin1String("text/uri-list") /* << QLatin1String( "application/x-kde-cutselection" ) */ // TODO //<< QLatin1String( "text/plain" ) << QLatin1String("application/x-kde-urilist"); } bool SvnItemModel::dropUrls(const QList &data, Qt::DropAction action, int row, int column, const QModelIndex &parent, bool intern) { Q_UNUSED(row); Q_UNUSED(column); if (action == Qt::IgnoreAction) { return true; } if (action == Qt::LinkAction) { return false; } emit urlDropped(data, action, parent, intern); return true; } QMimeData *SvnItemModel::mimeData(const QModelIndexList &indexes)const { QList urls; foreach (const QModelIndex &index, indexes) { if (index.column() == 0) { urls << m_Data->nodeForIndex(index)->kdeName(m_Data->m_Display->baseRevision()); } } QMimeData *mimeData = new QMimeData(); mimeData->setUrls(urls); KUrlMimeData::MetaDataMap metaMap; metaMap[QStringLiteral("kdesvn-source")] = QLatin1Char('t'); metaMap[QStringLiteral("kdesvn-id")] = uniqueIdentifier(); KUrlMimeData::setMetaData(metaMap, mimeData); return mimeData; } void SvnItemModel::makeIgnore(const QModelIndex &index) { if (!index.isValid()) { return; } SvnItemModelNode *node = m_Data->nodeForIndex(index); if (!node || node == m_Data->m_rootNode || node->isRealVersioned()) { return; } SvnItemModelNodeDir *pa = node->parent(); if (!pa) { return; } if (m_Data->m_SvnActions->makeIgnoreEntry(node, node->isIgnored())) { refreshIndex(index); refreshItem(pa); } } bool SvnItemModel::refreshItem(SvnItemModelNode *item) { if (!item || item == m_Data->m_rootNode) { return false; } try { item->setStat(m_Data->m_SvnActions->svnclient()->singleStatus(item->fullName(), false, m_Data->m_Display->baseRevision())); } catch (const svn::ClientException &e) { item->setStat(svn::StatusPtr(new svn::Status)); return false; } return true; } bool SvnItemModel::refreshIndex(const QModelIndex &ind, bool sendSignal) { bool ret = refreshItem(m_Data->nodeForIndex(ind)); if (sendSignal) { emit dataChanged(ind, ind); } return ret; } SvnItemModelNode *SvnItemModel::findPath(const svn::Path &_p) { QString ip = _p.path(); SvnItemModelNode *n1 = firstRootChild(); if (n1) { if (n1->fullName().length() < ip.length()) { ip = ip.right(ip.length() - n1->fullName().length()); } else if (n1->fullName() == ip) { return n1; } if (!n1->isDir()) { - return 0; + return nullptr; } const QVector lp = ip.splitRef(QLatin1Char('/'), QString::SkipEmptyParts); SvnItemModelNodeDir *d1 = static_cast(n1); return d1->findPath(lp); } - return 0; + return nullptr; } QModelIndex SvnItemModel::findIndex(const svn::Path &_p) { return m_Data->indexForNode(findPath(_p)); } void SvnItemModel::initDirWatch() { delete m_Data->m_DirWatch; - m_Data->m_DirWatch = 0; + m_Data->m_DirWatch = nullptr; if (m_Data->m_Display->isWorkingCopy()) { m_Data->m_DirWatch = new KDirWatch(this); connect(m_Data->m_DirWatch, SIGNAL(dirty(QString)), this, SLOT(slotDirty(QString))); connect(m_Data->m_DirWatch, SIGNAL(created(QString)), this, SLOT(slotCreated(QString))); connect(m_Data->m_DirWatch, SIGNAL(deleted(QString)), this, SLOT(slotDeleted(QString))); if (m_Data->m_DirWatch) { m_Data->m_DirWatch->addDir(m_Data->m_Display->baseUri() + QLatin1Char('/'), KDirWatch::WatchDirOnly); m_Data->m_DirWatch->startScan(true); } } } void SvnItemModel::slotCreated(const QString &what) { QModelIndex ind = findIndex(what); if (!ind.isValid()) { return; } SvnItemModelNode *n = static_cast(ind.internalPointer()); if (!n) { return; } if (n->isRealVersioned()) { refreshIndex(ind); } } void SvnItemModel::slotDeleted(const QString &what) { QModelIndex ind = findIndex(what); if (!ind.isValid()) { m_Data->m_DirWatch->removeDir(what); m_Data->m_DirWatch->removeFile(what); return; } SvnItemModelNode *n = static_cast(ind.internalPointer()); if (!n) { return; } if (!n->isRealVersioned()) { SvnItemModelNodeDir *p = n->parent(); QModelIndex pi = m_Data->indexForNode(p); if (!pi.isValid()) { return; } if (ind.row() >= p->m_Children.count()) { return; } beginRemoveRows(pi, ind.row(), ind.row()); p->m_Children.removeAt(ind.row()); endRemoveRows(); if (n->isDir()) { m_Data->m_DirWatch->removeDir(what); } else { m_Data->m_DirWatch->removeFile(what); } } else { refreshIndex(ind); } } void SvnItemModel::checkAddNewItems(const QModelIndex &ind) { SvnItemModelNodeDir *n = static_cast(ind.internalPointer()); QString what = n->fullName(); svn::StatusEntries dlist; while (what.endsWith(QLatin1Char('/'))) { what.chop(1); } if (!svnWrapper()->makeStatus(what, dlist, m_Data->m_Display->baseRevision(), false, true, true)) { return; } svn::StatusEntries::iterator it; for (it = dlist.begin(); it != dlist.end();) { if (n->contains((*it)->path()) || (*it)->path() == what) { it = dlist.erase(it); } else { ++it; } } if (!dlist.isEmpty()) { insertDirs(n, dlist); } } void SvnItemModel::slotDirty(const QString &what) { QModelIndex ind = findIndex(what); if (!ind.isValid()) { return; } SvnItemModelNode *n = static_cast(ind.internalPointer()); if (!n) { return; } if (n->isRealVersioned()) { if (!n->isDir()) { refreshIndex(ind); } else { checkAddNewItems(ind); } } else if (n->isDir()) { checkUnversionedDirs(n); } } bool SvnItemModel::checkRootNode() { if (!m_Data->m_rootNode) { return false; } try { m_Data->m_rootNode->setStat(m_Data->m_SvnActions->svnclient()->singleStatus(m_Data->m_Display->baseUri(), false, m_Data->m_Display->baseRevision())); } catch (const svn::ClientException &e) { m_Data->m_rootNode->setStat(svn::StatusPtr(new svn::Status)); emit clientException(e.msg()); return false; } return true; } bool SvnItemModel::refreshCurrentTree() { bool check_created = false; if (!m_Data->m_rootNode) { return false; } SvnItemModelNodeDir *_start = m_Data->m_rootNode; if (m_Data->m_Display->isWorkingCopy()) { if (!m_Data->m_rootNode->m_Children.isEmpty() && m_Data->m_rootNode->m_Children.at(0)->NodeIsDir()) { _start = static_cast(m_Data->m_rootNode->m_Children.at(0)); refreshItem(_start); } else { return false; } } else { if (!checkRootNode()) { return false; } _start = m_Data->m_rootNode; check_created = true; } return refreshDirnode(_start, check_created); } bool SvnItemModel::refreshDirnode(SvnItemModelNodeDir *node, bool check_empty, bool notrec) { if (!node) { if (m_Data->m_Display->isWorkingCopy()) { return false; } else { if (!checkRootNode()) { return false; } node = m_Data->m_rootNode; } } QString what = (node != m_Data->m_rootNode) ? node->fullName() : m_Data->m_Display->baseUri(); if (node->m_Children.isEmpty() && !check_empty) { if (node->fullName() == m_Data->m_Display->baseUri()) { return refreshItem(node); } return true; } svn::StatusEntries dlist; if (!svnWrapper()->makeStatus(what, dlist, m_Data->m_Display->baseRevision())) { return false; } if (m_Data->m_Display->isWorkingCopy()) { svn::StatusEntries neweritems; svnWrapper()->getaddedItems(what, neweritems); dlist += neweritems; } svn::StatusEntries::iterator it = dlist.begin(); for (it = dlist.begin(); it != dlist.end(); ++it) { if ((*it)->path() == what) { dlist.erase(it); break; } } QModelIndex ind = m_Data->indexForNode(node); for (int i = 0; i < node->m_Children.size(); ++i) { bool found = false; for (it = dlist.begin(); it != dlist.end(); ++it) { if ((*it)->path() == node->m_Children[i]->fullName()) { found = true; break; } } if (!found) { SvnItemModelNode *n = node->m_Children[i]; beginRemoveRows(ind, i, i); node->m_Children.removeAt(i); delete n; endRemoveRows(); --i; } } for (it = dlist.begin(); it != dlist.end();) { int index = node->indexOf((*it)->path()); if (index != -1) { node->m_Children[index]->setStat((*it)); if (node->m_Children[index]->NodeIsDir() != node->m_Children[index]->isDir()) { SvnItemModelNode *n = node->m_Children[index]; beginRemoveRows(ind, index, index); node->m_Children.removeAt(index); delete n; endRemoveRows(); } else { it = dlist.erase(it); } } else { ++it; } } // make sure that we do not read in the whole tree when just refreshing the current tree. if (!node->m_Children.isEmpty() && !notrec) { for (int i = 0; i < node->m_Children.size(); ++i) { if (node->m_Children[i]->NodeIsDir()) { // both other parameters makes no sense at this point - defaults refreshDirnode(static_cast(node->m_Children[i]), false, false); } } } // after so we don't recurse about it. insertDirs(node, dlist); if (!dlist.isEmpty()) { itemsFetched(m_Data->indexForNode(node)); } return true; } int SvnItemModel::checkUnversionedDirs(SvnItemModelNode *_parent) { if (!_parent || !_parent->isDir()) { // no toplevel unversioned - kdesvn is not a filemanager return 0; } QDir d(_parent->fullName()); d.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); QFileInfoList list = d.entryInfoList(); if (list.isEmpty()) { return 0; } svn::StatusEntries dlist; SvnItemModelNodeDir *n = static_cast(_parent); for (QFileInfoList::size_type i = 0; i < list.size(); ++i) { if (!(n->contains(list[i].absoluteFilePath()) || list[i].absoluteFilePath() == n->fullName())) { svn::StatusPtr stat(new svn::Status(list[i].absoluteFilePath())); dlist.append(stat); } } if (!dlist.isEmpty()) { insertDirs(_parent, dlist); } return dlist.size(); } const QString &SvnItemModel::uniqueIdentifier()const { return m_Data->m_Uid; } void SvnItemModel::slotNotifyMessage(const QString &msg) { qCDebug(KDESVN_LOG) << msg; } diff --git a/src/svnfrontend/models/svnitemmodel.h b/src/svnfrontend/models/svnitemmodel.h index 6c290b44..941d19fe 100644 --- a/src/svnfrontend/models/svnitemmodel.h +++ b/src/svnfrontend/models/svnitemmodel.h @@ -1,150 +1,150 @@ /*************************************************************************** * Copyright (C) 2008 by Rajko Albrecht ral@alwins-world.de * * http://kdesvn.alwins-world.de/ * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef SVNITEMMODEL_H #define SVNITEMMODEL_H #include #include "svnitemmodelfwd.h" #include "svnqt/svnqttypes.h" #include class SvnItemModelData; class QItemSelectionModel; class MainTreeWidget; class SvnActions; class QMimeData; namespace svn { class Path; } #define SORT_ROLE Qt::UserRole+1 #define FILTER_ROLE Qt::UserRole+2 #define BG_ROLE Qt::UserRole+3 class SvnItemModel: public QAbstractItemModel { Q_OBJECT public: - explicit SvnItemModel(MainTreeWidget *display, QObject *parent = 0); + explicit SvnItemModel(MainTreeWidget *display, QObject *parent = nullptr); virtual ~SvnItemModel(); void clear(); enum Column { Name = 0, Status, LastRevision, LastAuthor, LastDate, Locked, ColumnCount }; virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex())const; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole)const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole)const; virtual int columnCount(const QModelIndex &parent = QModelIndex())const; virtual int rowCount(const QModelIndex &parent = QModelIndex())const; virtual QModelIndex parent(const QModelIndex &index)const; virtual bool hasChildren(const QModelIndex &parent = QModelIndex())const; virtual bool canFetchMore(const QModelIndex &parent)const; virtual void fetchMore(const QModelIndex &parent); virtual Qt::ItemFlags flags(const QModelIndex &index)const; //! Returns the very first item in list. /*! * This item marks the working copy itself when a working copy is opened. * When opened a repository it is just an entry. */ SvnItemModelNode *firstRootChild(); SvnItemModelNode *nodeForIndex(const QModelIndex &index); QModelIndex firstRootIndex(); void setRootNodeStat(const svn::StatusPtr &); SvnActions *svnWrapper(); int checkDirs(const QString &_what, SvnItemModelNode *parent); virtual Qt::DropActions supportedDropActions()const; virtual QStringList mimeTypes()const; QMimeData *mimeData(const QModelIndexList &indexes)const; bool dropUrls(const QList &data, Qt::DropAction action, int row, int column, const QModelIndex &parent, bool intern); bool filterIndex(const QModelIndex &, int, svnmodel::ItemTypeFlag)const; /* svn actions starts here */ void makeIgnore(const QModelIndex &); //! looks if \a aPath exists in tree /*! Looks always for perfect match, * \return node of matched item or 0 */ SvnItemModelNode *findPath(const svn::Path &aPath); //! looks if \a aPath exists in tree /*! Looks always for perfect match, * \return QModelIndex of matched item or invalid QModelIndex */ QModelIndex findIndex(const svn::Path &aPath); void initDirWatch(); bool refreshCurrentTree(); bool refreshDirnode(SvnItemModelNodeDir *, bool check_empty = false, bool notrec = false); bool refreshItem(SvnItemModelNode *); bool refreshIndex(const QModelIndex &, bool sendSignal = true); void clearNodeDir(SvnItemModelNodeDir *); const QString &uniqueIdentifier()const; Q_SIGNALS: void urlDropped(const QList &, Qt::DropAction, const QModelIndex &, bool); void clientException(const QString &); void itemsFetched(const QModelIndex &); protected: /* the parent entry must removed from list before */ void insertDirs(SvnItemModelNode *_parent, svn::StatusEntries &); //! \a ind must be a directory index void checkAddNewItems(const QModelIndex &ind); bool checkRootNode(); int checkUnversionedDirs(SvnItemModelNode *_parent); void beginRemoveRows(const QModelIndex &parent, int first, int last); public Q_SLOTS: virtual void slotNotifyMessage(const QString &); protected Q_SLOTS: void slotCreated(const QString &); void slotDeleted(const QString &); void slotDirty(const QString &); private: friend class SvnItemModelData; QScopedPointer m_Data; virtual bool insertRows(int , int, const QModelIndex & = QModelIndex()); virtual bool insertColumns(int, int, const QModelIndex & = QModelIndex()); virtual bool removeRows(int, int, const QModelIndex & = QModelIndex()); virtual bool removeColumns(int, int, const QModelIndex & = QModelIndex()); }; #endif diff --git a/src/svnfrontend/models/svnitemnode.cpp b/src/svnfrontend/models/svnitemnode.cpp index 2a012287..69f91145 100644 --- a/src/svnfrontend/models/svnitemnode.cpp +++ b/src/svnfrontend/models/svnitemnode.cpp @@ -1,215 +1,215 @@ /*************************************************************************** * Copyright (C) 2008 by Rajko Albrecht ral@alwins-world.de * * http://kdesvn.alwins-world.de/ * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "svnitemnode.h" #include "svnfrontend/maintreewidget.h" #include "svnqt/revision.h" #include "settings/kdesvnsettings.h" SvnItemModelNode::SvnItemModelNode(SvnItemModelNodeDir *aParentNode, SvnActions *bl, MainTreeWidget *id) : SvnItem(), _parentNode(aParentNode), _actions(bl), _display(id) { } int SvnItemModelNode::rowNumber()const { if (!_parentNode) { return -1; } return _parentNode->childList().indexOf(const_cast(this)); } bool SvnItemModelNode::NodeIsDir() const { return false; } SvnItemModelNodeDir *SvnItemModelNode::parent()const { return _parentNode; } QColor SvnItemModelNode::backgroundColor() const { if (Kdesvnsettings::colored_state()) { switch (m_bgColor) { case UPDATES: return Kdesvnsettings::color_need_update(); case LOCKED: return Kdesvnsettings::color_locked_item(); case ADDED: return Kdesvnsettings::color_item_added(); case DELETED: return Kdesvnsettings::color_item_deleted(); case MODIFIED: return Kdesvnsettings::color_changed_item(); case MISSING: return Kdesvnsettings::color_missed_item(); case NOTVERSIONED: return Kdesvnsettings::color_notversioned_item(); case CONFLICT: return Kdesvnsettings::color_conflicted_item(); case NEEDLOCK: return Kdesvnsettings::color_need_lock(); case NONE: break; } } return QColor(); } bool SvnItemModelNode::NodeHasChilds() const { return false; } /************************ * Methods from SvnItem * ************************/ QString SvnItemModelNode::getParentDir()const { if (parent()) { return parent()->fullName(); } return QString(); } SvnItem *SvnItemModelNode::getParentItem()const { return _parentNode; } svn::Revision SvnItemModelNode::correctPeg()const { /// @todo backlink to remote revision storage return _display->baseRevision(); } void SvnItemModelNode::refreshStatus(bool children) { _display->refreshItem(this); if (!children && _parentNode) { _parentNode->refreshStatus(false); } } SvnActions *SvnItemModelNode::getWrapper() const { return _actions; } char SvnItemModelNode::sortChar() const { return 3; } SvnItemModelNodeDir::SvnItemModelNodeDir(SvnActions *bl, MainTreeWidget *disp) - : SvnItemModelNode(0, bl, disp), m_Children() + : SvnItemModelNode(nullptr, bl, disp), m_Children() { } SvnItemModelNodeDir::SvnItemModelNodeDir(SvnItemModelNodeDir *_parent, SvnActions *bl, MainTreeWidget *disp) : SvnItemModelNode(_parent, bl, disp), m_Children() { } SvnItemModelNodeDir::~SvnItemModelNodeDir() { clear(); } void SvnItemModelNodeDir::clear() { qDeleteAll(m_Children); m_Children.clear(); } const QVector &SvnItemModelNodeDir::childList()const { return m_Children; } bool SvnItemModelNodeDir::NodeIsDir() const { if (isValid()) { return isDir(); } return true; } SvnItemModelNode *SvnItemModelNodeDir::child(int row)const { if (row < 0 || row >= m_Children.size()) { - return 0; + return nullptr; } return m_Children[row]; } char SvnItemModelNodeDir::sortChar() const { return 1; } SvnItemModelNode *SvnItemModelNodeDir::findPath(const QVector &parts) { for (int i = 0; i < m_Children.size(); ++i) { if (m_Children[i]->shortName() == parts[0]) { if (parts.size() == 1) { return m_Children[i]; } else if (m_Children[i]->isDir()) { return static_cast(m_Children[i])->findPath(parts.mid(1)); } } } return nullptr; } bool SvnItemModelNodeDir::contains(const QString &fullName) const { return indexOf(fullName) != -1; } int SvnItemModelNodeDir::indexOf(const QString &fullPath) const { for (int i = 0; i < m_Children.size(); ++i) { if (m_Children[i]->fullName() == fullPath) { return i; } } return -1; } void SvnItemModelNodeDir::refreshStatus(bool children) { SvnItemModelNode::refreshStatus(children); if (!isValid()) { return; } if (children) { for (int i = 0; i < m_Children.size(); ++i) { m_Children[i]->refreshStatus(children); } } } bool SvnItemModelNodeDir::NodeHasChilds() const { return !isIgnored(); } diff --git a/src/svnfrontend/stopdlg.cpp b/src/svnfrontend/stopdlg.cpp index 0154f136..3413e7b2 100644 --- a/src/svnfrontend/stopdlg.cpp +++ b/src/svnfrontend/stopdlg.cpp @@ -1,211 +1,211 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "stopdlg.h" #include "ccontextlistener.h" #include "settings/kdesvnsettings.h" #include "helpers/stringhelper.h" #include #include #include #include #include #include #include #include #include StopDlg::StopDlg(QObject *listener, QWidget *parent, const QString &caption, const QString &text) : QDialog(parent) , m_Context(listener) , m_MinDuration(1000) , mCancelled(false) , mShown(false) , m_BarShown(false) , m_netBarShown(false) , cstack(nullptr) , m_bBox(new QDialogButtonBox(QDialogButtonBox::Cancel, this)) { setWindowTitle(caption); m_lastLogLines = 0; m_lastLog.clear(); mShowTimer = new QTimer(this); m_StopTick.start(); mainLayout = new QVBoxLayout(this); layout = new QVBoxLayout; mainLayout->addLayout(layout); mainLayout->addWidget(m_bBox); mLabel = new QLabel(text, this); layout->addWidget(mLabel); m_ProgressBar = new QProgressBar(this); m_ProgressBar->setRange(0, 15); m_ProgressBar->setTextVisible(false); layout->addWidget(m_ProgressBar); m_NetBar = new QProgressBar(this); m_NetBar->setRange(0, 15); layout->addWidget(m_NetBar); mWait = false; - m_LogWindow = 0; + m_LogWindow = nullptr; connect(mShowTimer, SIGNAL(timeout()), this, SLOT(slotAutoShow())); connect(m_bBox, SIGNAL(rejected()), this, SLOT(slotCancel())); if (m_Context) { connect(m_Context, SIGNAL(tickProgress()), this, SLOT(slotTick())); connect(m_Context, SIGNAL(waitShow(bool)), this, SLOT(slotWait(bool))); connect(m_Context, SIGNAL(netProgress(long long int,long long int)), this, SLOT(slotNetProgres(long long int,long long int))); connect(this, SIGNAL(sigCancel(bool)), m_Context, SLOT(setCanceled(bool))); } mShowTimer->setSingleShot(true); mShowTimer->start(m_MinDuration); setMinimumSize(280, 160); adjustSize(); } void StopDlg::showEvent(QShowEvent *e) { if (!cstack) { cstack = new CursorStack(Qt::BusyCursor); } QDialog::showEvent(e); } void StopDlg::hideEvent(QHideEvent *e) { delete cstack; cstack = nullptr; QDialog::hideEvent(e); } void StopDlg::slotWait(bool how) { mWait = how; if (mShown && mWait) { hide(); mShown = false; } } StopDlg::~StopDlg() { delete cstack; } void StopDlg::slotAutoShow() { bool hasDialogs = false; QWidget *w = QApplication::activeModalWidget(); if (w && w != this && w != parentWidget()) { hasDialogs = true; } if (hasDialogs) { hide(); } if (mShown || mWait || hasDialogs) { mShowTimer->setSingleShot(true); if (mWait) { //qCDebug(KDESVN_LOG) << "Waiting for show"<start(m_MinDuration); } mShowTimer->start(m_MinDuration); return; } m_ProgressBar->hide(); m_NetBar->hide(); m_BarShown = false; m_netBarShown = false; show(); QCoreApplication::processEvents(); mShown = true; mShowTimer->setSingleShot(true); mShowTimer->start(m_MinDuration); } void StopDlg::slotCancel() { mCancelled = true; emit sigCancel(true); } void StopDlg::slotTick() { if (m_StopTick.elapsed() > 500) { if (!m_BarShown) { m_ProgressBar->show(); m_BarShown = true; } if (m_ProgressBar->value() == 15) { m_ProgressBar->reset(); } else { m_ProgressBar->setValue(m_ProgressBar->value() + 1); } m_StopTick.restart(); QCoreApplication::processEvents(); } } void StopDlg::slotExtraMessage(const QString &msg) { ++m_lastLogLines; if (!m_LogWindow) { m_LogWindow = new QTextBrowser(this); layout->addWidget(m_LogWindow); m_LogWindow->show(); resize(QSize(500, 400).expandedTo(minimumSizeHint())); } if (m_lastLogLines >= Kdesvnsettings::self()->cmdline_log_minline() && isHidden()) { slotAutoShow(); } m_LogWindow->append(msg); QCoreApplication::processEvents(); } void StopDlg::slotNetProgres(long long int current, long long int max) { if (m_StopTick.elapsed() > 300 || (m_BarShown && !m_netBarShown)) { if (!m_netBarShown) { m_NetBar->show(); m_netBarShown = true; } QString s1 = helpers::ByteToString(current); if (max > -1 && max != m_NetBar->maximum()) { QString s2 = helpers::ByteToString(max); m_NetBar->setFormat(i18n("%p% of %1", s2)); m_NetBar->setRange(0, max); } if (max == -1) { if (m_NetBar->maximum() == -1 || m_NetBar->maximum() < current) { m_NetBar->setFormat(i18n("%1 transferred.", s1)); m_NetBar->setRange(0, current + 1); } else { m_NetBar->setFormat(i18n("%1 of %2", s1, helpers::ByteToString(m_NetBar->maximum()))); } } m_NetBar->setValue(current); m_StopTick.restart(); QCoreApplication::processEvents(); } } diff --git a/src/svnfrontend/svnactions.cpp b/src/svnfrontend/svnactions.cpp index 3bd2fe6a..bcb7a855 100644 --- a/src/svnfrontend/svnactions.cpp +++ b/src/svnfrontend/svnactions.cpp @@ -1,2922 +1,2922 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "svnactions.h" #include "checkoutinfo_impl.h" #include "itemdisplay.h" #include "svnitem.h" #include "rangeinput_impl.h" #include "propertiesdlg.h" #include "ccontextlistener.h" #include "tcontextlistener.h" #include "modifiedthread.h" #include "fillcachethread.h" #include "svnlogdlgimp.h" #include "stopdlg.h" #include "blamedisplay.h" #include "ksvnwidgets/commitmsg_impl.h" #include "ksvnwidgets/models/commitmodelhelper.h" #include "ksvnwidgets/diffbrowser.h" #include "ksvnwidgets/encodingselector_impl.h" #include "ksvnwidgets/revertform.h" #include "graphtree/revisiontree.h" #include "settings/kdesvnsettings.h" #include "svnqt/client.h" #include "svnqt/annotate_line.h" #include "svnqt/context_listener.h" #include "svnqt/dirent.h" #include "svnqt/targets.h" #include "svnqt/url.h" #include "svnqt/svnqttypes.h" #include "svnqt/svnqt_defines.h" #include "svnqt/client_parameter.h" #include "svnqt/client_commit_parameter.h" #include "svnqt/client_annotate_parameter.h" #include "svnqt/client_update_parameter.h" #include "svnqt/cache/LogCache.h" #include "svnqt/cache/ReposLog.h" #include "svnqt/cache/ReposConfig.h" #include "fronthelpers/watchedprocess.h" #include "helpers/stringhelper.h" #include "helpers/kdesvn_debug.h" #include "helpers/ktranslateurl.h" #include "helpers/windowgeometryhelper.h" #include "fronthelpers/cursorstack.h" #include "cacheentry.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /// @todo has to be removed for a real fix of ticket #613 #include // wait not longer than 10 seconds for a thread #define MAX_THREAD_WAITTIME 10000 class SvnActionsData { public: SvnActionsData() - : m_ParentList(NULL) - , m_SvnContextListener(NULL) + : m_ParentList(nullptr) + , m_SvnContextListener(nullptr) , m_Svnclient(svn::Client::getobject(svn::ContextP())) , runblocked(false) { } ~SvnActionsData() { cleanDialogs(); delete m_SvnContextListener; } static bool isExternalDiff() { if (Kdesvnsettings::use_external_diff()) { const QString edisp = Kdesvnsettings::external_diff_display(); const QVector wlist = edisp.splitRef(QLatin1Char(' ')); if (wlist.count() >= 3 && edisp.contains(QLatin1String("%1")) && edisp.contains(QLatin1String("%2"))) { return true; } } return false; } void clearCaches() { QWriteLocker wl(&(m_InfoCacheLock)); m_PropertiesCache.clear(); m_contextData.clear(); m_InfoCache.clear(); } void cleanDialogs() { if (m_DiffDialog) { delete m_DiffDialog; m_DiffDialog = nullptr; } if (m_LogDialog) { m_LogDialog->saveSize(); delete m_LogDialog; m_LogDialog = nullptr; } } /// @todo set some standards options to svn::Context. This should made via a Config class in svnqt (future release 1.4) /// this is a workaround for ticket #613 void setStandards() { if (!m_CurrentContext) { return; } svn_config_t *cfg_config = static_cast(apr_hash_get(m_CurrentContext->ctx()->config, SVN_CONFIG_CATEGORY_CONFIG, APR_HASH_KEY_STRING)); if (!cfg_config) { return; } svn_config_set(cfg_config, SVN_CONFIG_SECTION_HELPERS, - SVN_CONFIG_OPTION_DIFF_CMD, 0L); + SVN_CONFIG_OPTION_DIFF_CMD, nullptr); } ItemDisplay *m_ParentList; CContextListener *m_SvnContextListener; svn::ContextP m_CurrentContext; svn::ClientP m_Svnclient; helpers::statusCache m_UpdateCache; helpers::statusCache m_Cache; helpers::statusCache m_conflictCache; helpers::statusCache m_repoLockCache; helpers::itemCache m_PropertiesCache; /// \todo as persistent cache (sqlite?) helpers::itemCache m_InfoCache; helpers::itemCache m_MergeInfoCache; QPointer m_DiffBrowserPtr; QPointer m_DiffDialog; QPointer m_LogDialog; QMap m_contextData; QReadWriteLock m_InfoCacheLock; bool runblocked; }; #define EMIT_FINISHED emit sendNotify(i18n("Finished")) #define EMIT_REFRESH emit sigRefreshAll() #define DIALOGS_SIZES "display_dialogs_sizes" SvnActions::SvnActions(ItemDisplay *parent, bool processes_blocked) : QObject(parent ? parent->realWidget() : nullptr) , SimpleLogCb() , m_CThread(nullptr) , m_UThread(nullptr) , m_FCThread(nullptr) { m_Data.reset(new SvnActionsData); m_Data->m_ParentList = parent; m_Data->m_SvnContextListener = new CContextListener(this); m_Data->runblocked = processes_blocked; connect(m_Data->m_SvnContextListener, SIGNAL(sendNotify(QString)), this, SLOT(slotNotifyMessage(QString))); } svn::ClientP SvnActions::svnclient() { return m_Data->m_Svnclient; } SvnActions::~SvnActions() { killallThreads(); } void SvnActions::slotNotifyMessage(const QString &aMsg) { emit sendNotify(aMsg); } void SvnActions::reInitClient() { m_Data->clearCaches(); m_Data->cleanDialogs(); if (m_Data->m_CurrentContext) { - m_Data->m_CurrentContext->setListener(0L); + m_Data->m_CurrentContext->setListener(nullptr); } m_Data->m_CurrentContext = svn::ContextP(new svn::Context); m_Data->m_CurrentContext->setListener(m_Data->m_SvnContextListener); m_Data->m_Svnclient->setContext(m_Data->m_CurrentContext); ///@todo workaround has to be replaced m_Data->setStandards(); } void SvnActions::makeLog(const svn::Revision &start, const svn::Revision &end, const svn::Revision &peg, const QString &which, bool follow, bool list_files, int limit) { svn::LogEntriesMapPtr logs = getLog(start, end, peg, which, list_files, limit, follow); if (!logs) { return; } svn::InfoEntry info; if (!singleInfo(which, peg, info)) { return; } const QString reposRoot = info.reposRoot().toString(); - bool need_modal = m_Data->runblocked || QApplication::activeModalWidget() != 0; + bool need_modal = m_Data->runblocked || QApplication::activeModalWidget() != nullptr; if (need_modal || !m_Data->m_LogDialog) { m_Data->m_LogDialog = new SvnLogDlgImp(this, need_modal); connect(m_Data->m_LogDialog, SIGNAL(makeDiff(QString,svn::Revision,QString,svn::Revision,QWidget*)), this, SLOT(makeDiff(QString,svn::Revision,QString,svn::Revision,QWidget*))); connect(m_Data->m_LogDialog, SIGNAL(makeCat(svn::Revision,QString,QString,svn::Revision,QWidget*)), this, SLOT(slotMakeCat(svn::Revision,QString,QString,svn::Revision,QWidget*))); } if (m_Data->m_LogDialog) { m_Data->m_LogDialog->dispLog(logs, info.url().toString().mid(reposRoot.length()), reposRoot, ( peg == svn::Revision::UNDEFINED ? (svn::Url::isValid(which) ? svn::Revision::HEAD : svn::Revision::UNDEFINED) : peg ), which); if (need_modal) { m_Data->m_LogDialog->exec(); m_Data->m_LogDialog->saveSize(); delete m_Data->m_LogDialog; } else { m_Data->m_LogDialog->show(); m_Data->m_LogDialog->raise(); } } EMIT_FINISHED; } svn::LogEntriesMapPtr SvnActions::getLog(const svn::Revision &start, const svn::Revision &end, const svn::Revision &peg, const QString &which, bool list_files, int limit, QWidget *parent) { return getLog(start, end, peg, which, list_files, limit, Kdesvnsettings::log_follows_nodes(), parent); } svn::LogEntriesMapPtr SvnActions::getLog(const svn::Revision &start, const svn::Revision &end, const svn::Revision &peg, const QString &which, bool list_files, int limit, bool follow, QWidget *parent) { svn::LogEntriesMapPtr logs; if (!m_Data->m_CurrentContext) { return logs; } bool mergeinfo = hasMergeInfo(m_Data->m_ParentList->baseUri().isEmpty() ? which : m_Data->m_ParentList->baseUri()); svn::LogParameter params; params.targets(which).revisionRange(start, end).peg(peg).includeMergedRevisions(mergeinfo).limit(limit).discoverChangedPathes(list_files).strictNodeHistory(!follow); try { StopDlg sdlg(m_Data->m_SvnContextListener, (parent ? parent : m_Data->m_ParentList->realWidget()), i18nc("@title:window", "Logs"), i18n("Getting logs - hit Cancel for abort")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); logs = svn::LogEntriesMapPtr(new svn::LogEntriesMap); if (doNetworking()) { if (!m_Data->m_Svnclient->log(params, *logs)) { logs.clear(); return logs; } } else { svn::InfoEntry e; if (!singleInfo(m_Data->m_ParentList->baseUri(), svn::Revision::BASE, e)) { logs.clear(); return logs; } if (svn::Url::isLocal(e.reposRoot().toString())) { if (!m_Data->m_Svnclient->log(params, *logs)) { logs.clear(); return logs; } } else { svn::cache::ReposLog rl(m_Data->m_Svnclient, e.reposRoot().toString()); QString what; const QString s1 = e.url().toString().mid(e.reposRoot().toString().length()); if (which == QLatin1String(".")) { what = s1; } else { const QString s2 = which.mid(m_Data->m_ParentList->baseUri().length()); what = s1 + QLatin1Char('/') + s2; } rl.log(what, start, end, peg, *logs, !follow, limit); } } } catch (const svn::Exception &e) { emit clientException(e.msg()); logs.clear(); } if (logs && logs->isEmpty()) { logs.clear(); emit clientException(i18n("Got no logs")); } return logs; } bool SvnActions::getSingleLog(svn::LogEntry &t, const svn::Revision &r, const QString &what, const svn::Revision &peg, QString &root) { bool res = false; if (what.isEmpty()) { return res; } if (root.isEmpty()) { svn::InfoEntry inf; if (!singleInfo(what, peg, inf)) { return res; } root = inf.reposRoot().toString(); } if (!svn::Url::isLocal(root)) { svn::LogEntriesMap _m; try { svn::cache::ReposLog rl(m_Data->m_Svnclient , root); if (rl.isValid() && rl.simpleLog(_m, r, r, true)) { const svn::LogEntriesMap::const_iterator it = _m.constFind(r.revnum()); if (it != _m.constEnd()) { t = it.value(); res = true; } } } catch (const svn::Exception &e) { emit clientException(e.msg()); } } if (!res) { svn::LogEntriesMapPtr log = getLog(r, r, peg, root, true, 1); if (log) { const svn::LogEntriesMap::const_iterator it = log->constFind(r.revnum()); if (it != log->constEnd()) { t = it.value(); res = true; } } } return res; } bool SvnActions::hasMergeInfo(const QString &originpath) { QVariant _m(false); QString path; svn::InfoEntry e; if (!singleInfo(originpath, svn::Revision::UNDEFINED, e)) { return false; } path = e.reposRoot().toString(); if (!m_Data->m_MergeInfoCache.findSingleValid(path, _m)) { bool mergeinfo; try { mergeinfo = m_Data->m_Svnclient->RepoHasCapability(path, svn::CapabilityMergeinfo); } catch (const svn::ClientException &e) { emit sendNotify(e.msg()); return false; } _m.setValue(mergeinfo); m_Data->m_MergeInfoCache.insertKey(_m, path); } return _m.toBool(); } bool SvnActions::singleInfo(const QString &what, const svn::Revision &_rev, svn::InfoEntry &target, const svn::Revision &_peg) { QString url; QString cacheKey; QTime d; d.start(); svn::Revision peg = _peg; if (!m_Data->m_CurrentContext) { return false; } #ifdef DEBUG_TIMER QTime _counttime; _counttime.start(); #endif if (!svn::Url::isValid(what)) { // working copy // url = svn::Wc::getUrl(what); url = what; if (_rev != svn::Revision::WORKING && url.contains(QLatin1Char('@'))) { url += QStringLiteral("@BASE"); } peg = svn::Revision::UNDEFINED; cacheKey = url; } else { // valid url QUrl _uri(what); QString prot = svn::Url::transformProtokoll(_uri.scheme()); _uri.setScheme(prot); url = _uri.toString(); if (peg == svn::Revision::UNDEFINED) { peg = _rev; } if (peg == svn::Revision::UNDEFINED) { peg = svn::Revision::HEAD; } cacheKey = _rev.toString() + QLatin1Char('/') + url; } svn::InfoEntries e; bool must_write = false; { QReadLocker rl(&(m_Data->m_InfoCacheLock)); if (cacheKey.isEmpty() || !m_Data->m_InfoCache.findSingleValid(cacheKey, target)) { must_write = true; try { e = (m_Data->m_Svnclient->info(url, svn::DepthEmpty, _rev, peg)); } catch (const svn::Exception &ce) { qCDebug(KDESVN_LOG) << "single info: " << ce.msg() << endl; emit clientException(ce.msg()); return false; } if (e.isEmpty() || e[0].reposRoot().isEmpty()) { emit clientException(i18n("Got no info.")); return false; } target = e[0]; } } if (must_write) { QWriteLocker wl(&(m_Data->m_InfoCacheLock)); if (!cacheKey.isEmpty()) { m_Data->m_InfoCache.insertKey(e[0], cacheKey); if (peg != svn::Revision::UNDEFINED && peg.kind() != svn::Revision::NUMBER && peg.kind() != svn::Revision::DATE) { // for persistent storage, store head into persistent cache makes no sense. cacheKey = e[0].revision().toString() + QLatin1Char('/') + url; m_Data->m_InfoCache.insertKey(e[0], cacheKey); } } } #ifdef DEBUG_TIMER qCDebug(KDESVN_LOG) << "Time getting info for " << cacheKey << ": " << _counttime.elapsed(); #endif return true; } void SvnActions::makeTree(const QString &what, const svn::Revision &_rev, const svn::Revision &startr, const svn::Revision &endr) { svn::InfoEntry info; if (!singleInfo(what, _rev, info)) { return; } const QString reposRoot = info.reposRoot().toString(); if (Kdesvnsettings::fill_cache_on_tree()) { stopFillCache(); } QPointer dlg(new KSvnSimpleOkDialog(QStringLiteral("revisiontree_dlg"), m_Data->m_ParentList->realWidget())); dlg->setWindowTitle(i18nc("@title:window", "History of %1", info.url().toString().mid(reposRoot.length()))); RevisionTree *rt(new RevisionTree(m_Data->m_Svnclient, m_Data->m_SvnContextListener, reposRoot, startr, endr, info.url().toString().mid(reposRoot.length()), _rev, dlg)); if (rt->isValid()) { QWidget *disp = rt->getView(); if (disp) { dlg->addWidget(rt->getView()); connect( disp, SIGNAL(makeNorecDiff(QString,svn::Revision,QString,svn::Revision,QWidget*)), this, SLOT(makeNorecDiff(QString,svn::Revision,QString,svn::Revision,QWidget*)) ); connect( disp, SIGNAL(makeRecDiff(QString,svn::Revision,QString,svn::Revision,QWidget*)), this, SLOT(makeDiff(QString,svn::Revision,QString,svn::Revision,QWidget*)) ); connect(disp, SIGNAL(makeCat(svn::Revision,QString,QString,svn::Revision,QWidget*)), this, SLOT(slotMakeCat(svn::Revision,QString,QString,svn::Revision,QWidget*))); dlg->exec(); } } delete dlg; } void SvnActions::makeBlame(const svn::Revision &start, const svn::Revision &end, SvnItem *k) { if (k) { makeBlame(start, end, k->fullName(), m_Data->m_ParentList->realWidget()); } } void SvnActions::makeBlame(const svn::Revision &start, const svn::Revision &end, const QString &k, QWidget *_p, const svn::Revision &_peg, SimpleLogCb *_acb) { if (!m_Data->m_CurrentContext) { return; } svn::AnnotatedFile blame; QWidget *_parent = _p ? _p : m_Data->m_ParentList->realWidget(); bool mergeinfo = hasMergeInfo(m_Data->m_ParentList->baseUri().isEmpty() ? k : m_Data->m_ParentList->baseUri()); svn::AnnotateParameter params; params.path(k).pegRevision(_peg == svn::Revision::UNDEFINED ? end : _peg).revisionRange(svn::RevisionRange(start, end)).includeMerged(mergeinfo); try { CursorStack a(Qt::BusyCursor); StopDlg sdlg(m_Data->m_SvnContextListener, _parent, i18nc("@title:window", "Annotate"), i18n("Annotate lines - hit Cancel for abort")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); m_Data->m_Svnclient->annotate(blame, params); } catch (const svn::Exception &e) { emit clientException(e.msg()); return; } if (blame.isEmpty()) { QString ex = i18n("Got no annotate"); emit clientException(ex); return; } EMIT_FINISHED; BlameDisplay::displayBlame(_acb ? _acb : this, k, blame, _p); } bool SvnActions::makeGet(const svn::Revision &start, const QString &what, const QString &target, const svn::Revision &peg, QWidget *_dlgparent) { if (!m_Data->m_CurrentContext) { return false; } CursorStack a(Qt::BusyCursor); QWidget *dlgp = _dlgparent ? _dlgparent : m_Data->m_ParentList->realWidget(); svn::Path p(what); try { StopDlg sdlg(m_Data->m_SvnContextListener, dlgp, i18nc("@title:window", "Content Get"), i18n("Getting content - hit Cancel for abort")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); m_Data->m_Svnclient->get(p, target, start, peg); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } catch (...) { QString ex = i18n("Error getting content"); emit clientException(ex); return false; } return true; } void SvnActions::slotMakeCat(const svn::Revision &start, const QString &what, const QString &disp, const svn::Revision &peg, QWidget *_dlgparent) { QTemporaryFile content; content.setAutoRemove(true); // required otherwise it will not generate a unique name... if (!content.open()) { emit clientException(i18n("Error while open temporary file")); return; } QString tname = content.fileName(); content.close(); QWidget *parent = _dlgparent ? _dlgparent : m_Data->m_ParentList->realWidget(); if (!makeGet(start, what, tname, peg, parent)) { return; } EMIT_FINISHED; QMimeDatabase db; const QMimeType mimeType(db.mimeTypeForFile(tname)); KService::List offers = KMimeTypeTrader::self()->query(mimeType.name(), QLatin1String("Application"), QLatin1String("Type == 'Application' or (exist Exec)")); if (offers.isEmpty() || offers.first()->exec().isEmpty()) { offers = KMimeTypeTrader::self()->query(mimeType.name(), QLatin1String("Application"), QLatin1String("Type == 'Application'")); } KService::List::ConstIterator it = offers.constBegin(); for (; it != offers.constEnd(); ++it) { if ((*it)->noDisplay()) { continue; } break; } if (it != offers.constEnd()) { content.setAutoRemove(false); KRun::runService(**it, QList() << QUrl::fromLocalFile(tname), QApplication::activeWindow(), true); return; } QFile file(tname); file.open(QIODevice::ReadOnly); const QByteArray co = file.readAll(); if (!co.isEmpty()) { QPointer dlg = new KSvnSimpleOkDialog(QStringLiteral("cat_display_dlg"), parent); dlg->setWindowTitle(i18nc("@title:window", "Content of %1", disp)); QTextBrowser *ptr = new QTextBrowser(dlg); ptr->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); ptr->setWordWrapMode(QTextOption::NoWrap); ptr->setReadOnly(true); ptr->setText(QString::fromUtf8(co, co.size())); dlg->addWidget(ptr); dlg->exec(); delete dlg; } else { KMessageBox::information(parent, i18n("Got no content.")); } } bool SvnActions::makeMkdir(const svn::Targets &targets, const QString &logMessage) { if (!m_Data->m_CurrentContext || targets.targets().isEmpty()) { return false; } try { m_Data->m_Svnclient->mkdir(targets, logMessage); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } return true; } QString SvnActions::makeMkdir(const QString &parentDir) { if (!m_Data->m_CurrentContext) { return QString(); } bool isOk = false; const QString ex = QInputDialog::getText(m_Data->m_ParentList->realWidget(), i18n("New folder"), i18n("Enter folder name:"), QLineEdit::Normal, QString(), &isOk); if (!isOk || ex.isEmpty()) { return QString(); } svn::Path target(parentDir); target.addComponent(ex); try { m_Data->m_Svnclient->mkdir(target, QString()); } catch (const svn::Exception &e) { emit clientException(e.msg()); return QString(); } return target.path(); } QString SvnActions::getInfo(const SvnItemList &lst, const svn::Revision &rev, const svn::Revision &peg, bool recursive, bool all) { QString res; for (auto it = lst.cbegin(); it != lst.cend(); ++it) { if (all) { res += QStringLiteral("

%1

").arg((*it)->fullName()); } res += getInfo((*it)->fullName(), rev, peg, recursive, all); } return res; } QString SvnActions::getInfo(const QString &_what, const svn::Revision &rev, const svn::Revision &peg, bool recursive, bool all) { if (!m_Data->m_CurrentContext) { return QString(); } svn::InfoEntries entries; if (recursive) { try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Details"), i18n("Retrieving information - hit Cancel for abort")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); QString path = _what; if (_what.contains(QLatin1Char('@')) && !svn::Url::isValid(_what)) { path += QLatin1String("@BASE"); } entries = (m_Data->m_Svnclient->info(path, recursive ? svn::DepthInfinity : svn::DepthEmpty, rev, peg)); } catch (const svn::Exception &e) { emit clientException(e.msg()); return QString(); } } else { svn::InfoEntry info; if (!singleInfo(_what, rev, info, peg)) { return QString(); } entries.append(info); } return getInfo(entries, _what, all); } QString SvnActions::getInfo(const svn::InfoEntries &entries, const QString &_what, bool all) { QString text; static QString rb(QStringLiteral("")); static QString re(QStringLiteral("\n")); static QString cs(QStringLiteral(":")); unsigned int val = 0; for (auto it = entries.begin(); it != entries.end(); ++it) { if (val > 0) { text += QStringLiteral(""); } ++val; text += QStringLiteral("

"); text += QStringLiteral(""); if (!(*it).Name().isEmpty()) { text += rb + i18n("Name") + cs + ((*it).Name()) + re; } if (all) { text += rb + i18n("URL") + cs + ((*it).url().toDisplayString()) + re; if (!(*it).reposRoot().toString().isEmpty()) { text += rb + i18n("Canonical repository URL") + cs + ((*it).reposRoot().toDisplayString()) + re; } if (!(*it).checksum().isEmpty()) { text += rb + i18n("Checksum") + cs + ((*it).checksum()) + re; } } text += rb + i18n("Type") + cs; switch ((*it).kind()) { case svn_node_none: text += i18n("Absent"); break; case svn_node_file: text += i18n("File"); break; case svn_node_dir: text += i18n("Folder"); break; case svn_node_unknown: default: text += i18n("Unknown"); break; } text += re; if ((*it).kind() == svn_node_file) { text += rb + i18n("Size") + cs; if ((*it).size() != svn::InfoEntry::SVNQT_SIZE_UNKNOWN) { text += helpers::ByteToString((*it).size()); } else if ((*it).working_size() != svn::InfoEntry::SVNQT_SIZE_UNKNOWN) { text += helpers::ByteToString((*it).working_size()); } text += re; } if (all) { text += rb + i18n("Schedule") + cs; switch ((*it).Schedule()) { case svn_wc_schedule_normal: text += i18n("Normal"); break; case svn_wc_schedule_add: text += i18n("Addition"); break; case svn_wc_schedule_delete: text += i18n("Deletion"); break; case svn_wc_schedule_replace: text += i18n("Replace"); break; default: text += i18n("Unknown"); break; } text += re; text += rb + i18n("UUID") + cs + ((*it).uuid()) + re; } text += rb + i18n("Last author") + cs + ((*it).cmtAuthor()) + re; if ((*it).cmtDate().IsValid()) { text += rb + i18n("Last committed") + cs + (*it).cmtDate().toString() + re; } text += rb + i18n("Last revision") + cs + (*it).cmtRev().toString() + re; if ((*it).textTime().IsValid()) { text += rb + i18n("Content last changed") + cs + (*it).textTime().toString() + re; } if (all) { if ((*it).propTime().IsValid()) { text += rb + i18n("Property last changed") + cs + (*it).propTime().toString() + re; } for (int _cfi = 0; _cfi < (*it).conflicts().size(); ++_cfi) { text += rb + i18n("New version of conflicted file") + cs + ((*it).conflicts()[_cfi]->theirFile()); } if ((*it).prejfile().length()) { text += rb + i18n("Property reject file") + cs + ((*it).prejfile()) + re; } if (!(*it).copyfromUrl().isEmpty()) { text += rb + i18n("Copy from URL") + cs + ((*it).copyfromUrl().toDisplayString()) + re; } if ((*it).lockEntry().Locked()) { text += rb + i18n("Lock token") + cs + ((*it).lockEntry().Token()) + re; text += rb + i18n("Owner") + cs + ((*it).lockEntry().Owner()) + re; text += rb + i18n("Locked on") + cs + (*it).lockEntry().Date().toString() + re; text += rb + i18n("Lock comment") + cs + (*it).lockEntry().Comment() + re; } else { svn::StatusPtr d; if (checkReposLockCache(_what, d) && d && d->lockEntry().Locked()) { text += rb + i18n("Lock token") + cs + (d->lockEntry().Token()) + re; text += rb + i18n("Owner") + cs + (d->lockEntry().Owner()) + re; text += rb + i18n("Locked on") + cs + d->lockEntry().Date().toString() + re; text += rb + i18n("Lock comment") + cs + d->lockEntry().Comment() + re; } } } text += QStringLiteral("

\n"); } return text; } void SvnActions::makeInfo(const SvnItemList &lst, const svn::Revision &rev, const svn::Revision &peg, bool recursive) { QStringList infoList; infoList.reserve(lst.size()); for (int i = 0; i < lst.size(); ++i) { const QString text = getInfo(lst.at(i)->fullName(), rev, peg, recursive, true); if (!text.isEmpty()) { infoList += text; } } showInfo(infoList); } void SvnActions::makeInfo(const QStringList &lst, const svn::Revision &rev, const svn::Revision &peg, bool recursive) { QStringList infoList; infoList.reserve(lst.size()); for (int i = 0; i < lst.size(); ++i) { const QString text = getInfo(lst.at(i), rev, peg, recursive, true); if (!text.isEmpty()) { infoList += text; } } showInfo(infoList); } void SvnActions::showInfo(const QStringList &infoList) { if (infoList.isEmpty()) { return; } QString text(QLatin1String("")); for (int i = 0; i < infoList.count(); ++i) { text += QLatin1String("

") + infoList.at(i) + QLatin1String("

"); } text += QLatin1String(""); QPointer dlg = new KSvnSimpleOkDialog(QStringLiteral("info_dialog"), QApplication::activeModalWidget()); dlg->setWindowTitle(i18nc("@title:window", "Infolist")); QTextBrowser *ptr = new QTextBrowser(dlg); dlg->addWidget(ptr); ptr->setReadOnly(true); ptr->setText(text); dlg->exec(); delete dlg; } void SvnActions::editProperties(SvnItem *k, const svn::Revision &rev) { if (!m_Data->m_CurrentContext) { return; } if (!k) { return; } QPointer dlg(new PropertiesDlg(k, svnclient(), rev)); connect(dlg, SIGNAL(clientException(QString)), m_Data->m_ParentList->realWidget(), SLOT(slotClientException(QString))); if (dlg->exec() != QDialog::Accepted) { delete dlg; return; } svn::PropertiesMap setList; QStringList delList; dlg->changedItems(setList, delList); changeProperties(setList, delList, k->fullName()); k->refreshStatus(); EMIT_FINISHED; delete dlg; } bool SvnActions::changeProperties(const svn::PropertiesMap &setList, const QStringList &delList, const QString &path, const svn::Depth &depth) { try { svn::PropertiesParameter params; params.path(path).depth(depth); StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Applying Properties"), i18n("
Applying
hit cancel for abort
")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); // propertyValue == QString::null -> delete property for (int pos = 0; pos < delList.size(); ++pos) { m_Data->m_Svnclient->propset(params.propertyName(delList.at(pos))); } for (svn::PropertiesMap::ConstIterator it = setList.begin(); it != setList.end(); ++it) { m_Data->m_Svnclient->propset(params.propertyName(it.key()).propertyValue(it.value())); } } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } return true; } /*! \fn SvnActions::slotCommit() */ void SvnActions::doCommit(const SvnItemList &which) { if (!m_Data->m_CurrentContext || !m_Data->m_ParentList->isWorkingCopy()) { return; } SvnItemList::const_iterator liter = which.begin(); svn::Paths targets; if (which.isEmpty()) { targets.push_back(svn::Path(QStringLiteral("."))); } else { targets.reserve(which.size()); for (; liter != which.end(); ++liter) { targets.push_back(svn::Path( m_Data->m_ParentList->relativePath((*liter)) )); } } if (!m_Data->m_ParentList->baseUri().isEmpty()) { if (!QDir::setCurrent(m_Data->m_ParentList->baseUri())) { QString msg = i18n("Could not change to folder %1\n", m_Data->m_ParentList->baseUri()) + QString::fromLocal8Bit(strerror(errno)); emit sendNotify(msg); } } if (makeCommit(svn::Targets(targets)) && Kdesvnsettings::log_cache_on_open()) { startFillCache(m_Data->m_ParentList->baseUri(), true); } } bool SvnActions::makeCommit(const svn::Targets &targets) { bool ok, keeplocks; svn::Depth depth; svn::Revision nnum; bool review = Kdesvnsettings::review_commit(); QString msg; if (!doNetworking()) { emit clientException(i18n("Not commit because networking is disabled")); return false; } svn::CommitParameter commit_parameters; stopFillCache(); if (!review) { msg = Commitmsg_impl::getLogmessage(&ok, &depth, &keeplocks, m_Data->m_ParentList->realWidget()); if (!ok) { return false; } commit_parameters.targets(targets); } else { CommitActionEntries _check, _uncheck, _result; svn::StatusEntries _Cache; depth = svn::DepthEmpty; svn::StatusParameter params; params.depth(svn::DepthInfinity).all(false).update(false).noIgnore(false).revision(svn::Revision::HEAD); /// @todo filter out double entries for (size_t j = 0; j < targets.size(); ++j) { try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Status / List"), i18n("Creating list / check status")); _Cache = m_Data->m_Svnclient->status(params.path(targets.target(j).path())); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } for (int i = 0; i < _Cache.count(); ++i) { const svn::StatusPtr ptr = _Cache.at(i); const QString _p = ptr->path(); // check the node status, not the text status (it does not cover the prop status) if (ptr->isRealVersioned() && ( ptr->nodeStatus() == svn_wc_status_modified || ptr->nodeStatus() == svn_wc_status_added || ptr->nodeStatus() == svn_wc_status_replaced || ptr->nodeStatus() == svn_wc_status_deleted || ptr->nodeStatus() == svn_wc_status_modified )) { if (ptr->nodeStatus() == svn_wc_status_deleted) { _check.append(CommitActionEntry(_p, i18n("Delete"), CommitActionEntry::DELETE)); } else { _check.append(CommitActionEntry(_p, i18n("Commit"), CommitActionEntry::COMMIT)); } } else if (ptr->nodeStatus() == svn_wc_status_missing) { _uncheck.append(CommitActionEntry(_p, i18n("Delete and Commit"), CommitActionEntry::MISSING_DELETE)); } else if (!ptr->isVersioned()) { _uncheck.append(CommitActionEntry(_p, i18n("Add and Commit"), CommitActionEntry::ADD_COMMIT)); } } } msg = Commitmsg_impl::getLogmessage(_check, _uncheck, this, _result, &ok, &keeplocks, m_Data->m_ParentList->realWidget()); if (!ok || _result.isEmpty()) { return false; } svn::Paths _add, _commit, _delete; depth = svn::DepthInfinity; for (long i = 0; i < _result.count(); ++i) { _commit.append(_result[i].name()); if (_result[i].type() == CommitActionEntry::ADD_COMMIT) { _add.append(_result[i].name()); } else if (_result[i].type() == CommitActionEntry::MISSING_DELETE) { _delete.append(_result[i].name()); } } if (!_add.isEmpty()) { if (!addItems(_add, svn::DepthEmpty)) { return false; } } if (!_delete.isEmpty()) { makeDelete(svn::Targets(_delete)); } commit_parameters.targets(svn::Targets(_commit)); } commit_parameters.keepLocks(keeplocks).depth(depth).message(msg); try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Commit"), i18n("Commit - hit Cancel for abort")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); nnum = m_Data->m_Svnclient->commit(commit_parameters); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } EMIT_REFRESH; emit sendNotify(i18n("Committed revision %1.", nnum.toString())); return true; } void SvnActions::slotProcessDataRead(const QByteArray &data, WatchedProcess *) { emit sendNotify(QString::fromLocal8Bit(data)); } bool SvnActions::get(const QString &what, const QString &to, const svn::Revision &rev, const svn::Revision &peg, QWidget *p) { svn::Revision _peg = peg; if (_peg == svn::Revision::UNDEFINED) { _peg = rev; } try { StopDlg sdlg(m_Data->m_SvnContextListener, p ? p : m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Downloading"), i18n("Download - hit Cancel for abort")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); m_Data->m_Svnclient->get(svn::Path(what), to, rev, _peg); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } return true; } /*! \fn SvnActions::makeDiff(const QString&,const svn::Revision&start,const svn::Revision&end) */ void SvnActions::makeDiff(const QString &what, const svn::Revision &start, const svn::Revision &end, const svn::Revision &_peg, bool isDir) { makeDiff(what, start, what, end, _peg, isDir, m_Data->m_ParentList->realWidget()); } void SvnActions::makeDiff(const QString &p1, const svn::Revision &start, const QString &p2, const svn::Revision &end) { - makeDiff(p1, start, p2, end, (QWidget *)0); + makeDiff(p1, start, p2, end, (QWidget *)nullptr); } void SvnActions::makeDiff(const QString &p1, const svn::Revision &start, const QString &p2, const svn::Revision &end, QWidget *p) { if (!doNetworking() && start != svn::Revision::BASE && end != svn::Revision::WORKING) { emit sendNotify(i18n("Can not do this diff because networking is disabled.")); return; } if (m_Data->isExternalDiff()) { svn::InfoEntry info; if (singleInfo(p1, start, info)) { makeDiff(p1, start, p2, end, end, info.isDir(), p); } return; } makeDiffinternal(p1, start, p2, end, p); } void SvnActions::makeDiffExternal(const QString &p1, const svn::Revision &start, const QString &p2, const svn::Revision &end, const svn::Revision &_peg, bool isDir, QWidget *p, bool rec) { QFileInfo f1(p1); QFileInfo f2(p2); QTemporaryFile tfile(QDir::tempPath() + QLatin1Char('/') + f1.fileName() + QLatin1Char('-') + start.toString()); QTemporaryFile tfile2(QDir::tempPath() + QLatin1Char('/') + f2.fileName() + QLatin1Char('-') + end.toString()); QString s1 = f1.fileName() + QLatin1Char('-') + start.toString(); QString s2 = f2.fileName() + QLatin1Char('-') + end.toString(); if (f1.fileName() == f2.fileName() && p1 != p2) { s2.append(QStringLiteral("-sec")); } QTemporaryDir tdir1; tdir1.setAutoRemove(true); tfile.setAutoRemove(true); tfile2.setAutoRemove(true); tfile.open(); tfile2.open(); QString first, second; svn::Revision peg = _peg; if (start != svn::Revision::WORKING) { first = isDir ? tdir1.path() + QLatin1Char('/') + s1 : tfile.fileName(); } else { first = p1; } if (end != svn::Revision::WORKING) { second = isDir ? tdir1.path() + QLatin1Char('/') + s2 : tfile2.fileName(); } else { second = p2; } if (second == first) { KMessageBox::error(m_Data->m_ParentList->realWidget(), i18n("Both entries seems to be the same, can not diff.")); return; } if (start != svn::Revision::WORKING) { if (!isDir) { if (!get(p1, tfile.fileName(), start, peg, p)) { return; } } else { if (!makeCheckout(p1, first, start, peg, rec ? svn::DepthInfinity : svn::DepthFiles, true, false, false, false, false, p)) { return; } } } if (end != svn::Revision::WORKING) { if (!isDir) { if (!get(p2, tfile2.fileName(), end, peg, p)) { return; } } else { if (!makeCheckout(p2, second, end, peg, rec ? svn::DepthInfinity : svn::DepthFiles, true, false, false, false, false, p)) { return; } } } const QString edisp = Kdesvnsettings::external_diff_display(); const QVector wlist = edisp.splitRef(QLatin1Char(' ')); WatchedProcess *proc = new WatchedProcess(this); for (auto it = wlist.begin(); it != wlist.end(); ++it) { if (*it == QLatin1String("%1")) { *proc << first; } else if (*it == QLatin1String("%2")) { *proc << second; } else { *proc << (*it).toString(); } } proc->setAutoDelete(true); proc->setOutputChannelMode(KProcess::MergedChannels); connect(proc, SIGNAL(dataStderrRead(QByteArray,WatchedProcess*)), this, SLOT(slotProcessDataRead(QByteArray,WatchedProcess*))); connect(proc, SIGNAL(dataStdoutRead(QByteArray,WatchedProcess*)), this, SLOT(slotProcessDataRead(QByteArray,WatchedProcess*))); if (!isDir) { tfile2.setAutoRemove(false); tfile.setAutoRemove(false); proc->appendTempFile(tfile.fileName()); proc->appendTempFile(tfile2.fileName()); } else { tdir1.setAutoRemove(false); proc->appendTempDir(tdir1.path()); } tfile.close(); tfile2.close(); proc->start(); if (proc->waitForStarted(-1)) { if (m_Data->runblocked) { proc->waitForFinished(-1); } return; } else { emit sendNotify(i18n("Diff-process could not started, check command.")); } } void SvnActions::makeDiff(const QString &p1, const svn::Revision &start, const QString &p2, const svn::Revision &end, const svn::Revision &_peg, bool isDir, QWidget *p) { if (m_Data->isExternalDiff()) { makeDiffExternal(p1, start, p2, end, _peg, isDir, p); } else { makeDiffinternal(p1, start, p2, end, p, _peg); } } void SvnActions::makeDiffinternal(const QString &p1, const svn::Revision &r1, const QString &p2, const svn::Revision &r2, QWidget *p, const svn::Revision &_peg) { if (!m_Data->m_CurrentContext) { return; } QByteArray ex; QTemporaryDir tdir; tdir.setAutoRemove(true); QString tn(tdir.path() + QLatin1String("/svndiff")); QDir d1(tdir.path()); d1.mkdir(QStringLiteral("svndiff")); bool ignore_content = Kdesvnsettings::diff_ignore_content(); bool gitformat = Kdesvnsettings::diff_gitformat_default(); bool copy_as_add = Kdesvnsettings::diff_copies_as_add(); QWidget *parent = p ? p : m_Data->m_ParentList->realWidget(); QStringList extraOptions; if (Kdesvnsettings::diff_ignore_spaces()) { extraOptions.append(QStringLiteral("-b")); } if (Kdesvnsettings::diff_ignore_all_white_spaces()) { extraOptions.append(QStringLiteral("-w")); } svn::Revision peg = _peg == svn::Revision::UNDEFINED ? r2 : _peg; svn::DiffParameter _opts; _opts.path1(p1).path2(p2).tmpPath(tn). peg(peg).rev1(r1).rev2(r2). ignoreContentType(ignore_content).extra(svn::StringArray(extraOptions)).depth(svn::DepthInfinity).ignoreAncestry(false).noDiffDeleted(false).changeList(svn::StringArray()). git_diff_format(gitformat).copies_as_adds(copy_as_add); try { StopDlg sdlg(m_Data->m_SvnContextListener, parent, i18nc("@title:window", "Diffing"), i18n("Diffing - hit Cancel for abort")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); if (p1 == p2 && (r1.isRemote() || r2.isRemote())) { ex = m_Data->m_Svnclient->diff_peg(_opts); } else { ex = m_Data->m_Svnclient->diff(_opts.relativeTo(p1 == p2 ? svn::Path(p1) : svn::Path())); } } catch (const svn::Exception &e) { emit clientException(e.msg()); return; } EMIT_FINISHED; if (ex.isEmpty()) { emit clientException(i18n("No difference to display")); return; } dispDiff(ex); } void SvnActions::makeNorecDiff(const QString &p1, const svn::Revision &r1, const QString &p2, const svn::Revision &r2, QWidget *_p) { if (!m_Data->m_CurrentContext) { return; } if (m_Data->isExternalDiff()) { svn::InfoEntry info; if (singleInfo(p1, r1, info)) { makeDiffExternal(p1, r1, p2, r2, r2, info.isDir(), _p, false); } return; } QStringList extraOptions; if (Kdesvnsettings::diff_ignore_spaces()) { extraOptions.append(QStringLiteral("-b")); } if (Kdesvnsettings::diff_ignore_all_white_spaces()) { extraOptions.append(QStringLiteral("-w")); } QByteArray ex; QTemporaryDir tdir; tdir.setAutoRemove(true); QString tn(tdir.path() + QLatin1String("/svndiff")); QDir d1(tdir.path()); d1.mkdir(QStringLiteral("svndiff")); bool ignore_content = Kdesvnsettings::diff_ignore_content(); svn::DiffParameter _opts; // no peg revision required _opts.path1(p1).path2(p2).tmpPath(tn). rev1(r1).rev2(r2). ignoreContentType(ignore_content).extra(svn::StringArray(extraOptions)).depth(svn::DepthEmpty).ignoreAncestry(false).noDiffDeleted(false).changeList(svn::StringArray()); try { StopDlg sdlg(m_Data->m_SvnContextListener, _p ? _p : m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Diffing"), i18n("Diffing - hit cancel for abort")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); ex = m_Data->m_Svnclient->diff(_opts); } catch (const svn::Exception &e) { emit clientException(e.msg()); return; } EMIT_FINISHED; if (ex.isEmpty()) { emit clientException(i18n("No difference to display")); return; } dispDiff(ex); } void SvnActions::dispDiff(const QByteArray &ex) { QString what = Kdesvnsettings::external_diff_display(); if (Kdesvnsettings::use_external_diff() && (!what.contains(QLatin1String("%1")) || !what.contains(QLatin1String("%2")))) { const QVector wlist = what.splitRef(QLatin1Char(' ')); WatchedProcess *proc = new WatchedProcess(this); bool fname_used = false; for (auto it = wlist.begin(); it != wlist.end(); ++it) { if (*it == QLatin1String("%f")) { QTemporaryFile tfile; tfile.setAutoRemove(false); tfile.open(); fname_used = true; QDataStream ds(&tfile); ds.writeRawData(ex, ex.size()); *proc << tfile.fileName(); proc->appendTempFile(tfile.fileName()); tfile.close(); } else { *proc << (*it).toString(); } } proc->setAutoDelete(true); proc->setOutputChannelMode(KProcess::MergedChannels); connect(proc, SIGNAL(dataStderrRead(QByteArray,WatchedProcess*)), this, SLOT(slotProcessDataRead(QByteArray,WatchedProcess*))); connect(proc, SIGNAL(dataStdoutRead(QByteArray,WatchedProcess*)), this, SLOT(slotProcessDataRead(QByteArray,WatchedProcess*))); proc->start(); if (proc->waitForStarted(-1)) { if (!fname_used) { proc->write(ex); proc->closeWriteChannel(); } if (m_Data->runblocked) { proc->waitForFinished(-1); } return; } else { emit sendNotify(i18n("Display process could not started, check command.")); } } - bool need_modal = m_Data->runblocked || QApplication::activeModalWidget() != 0; + bool need_modal = m_Data->runblocked || QApplication::activeModalWidget() != nullptr; if (need_modal || !m_Data->m_DiffBrowserPtr || !m_Data->m_DiffDialog) { if (!need_modal && m_Data->m_DiffBrowserPtr) { delete m_Data->m_DiffBrowserPtr; } QPointer dlg(new KSvnSimpleOkDialog(QStringLiteral("diff_display"))); if (!need_modal) { dlg->setParent(nullptr); } dlg->setWindowTitle(i18nc("@title:window", "Diff Display")); DiffBrowser *ptr(new DiffBrowser(dlg)); ptr->setText(ex); dlg->addWidget(ptr); EncodingSelector_impl *enc(new EncodingSelector_impl(dlg)); dlg->addWidget(enc); connect(enc, SIGNAL(TextCodecChanged(QString)), ptr, SLOT(slotTextCodecChanged(QString))); enc->setCurrentEncoding(Kdesvnsettings::locale_for_diff()); // saveAs QPushButton *pbSaveAs = new QPushButton(dlg->buttonBox()); KStandardGuiItem::assign(pbSaveAs, KStandardGuiItem::SaveAs); dlg->buttonBox()->addButton(pbSaveAs, QDialogButtonBox::ActionRole); connect(pbSaveAs, SIGNAL(clicked(bool)), ptr, SLOT(saveDiff())); dlg->buttonBox()->setStandardButtons(QDialogButtonBox::Close); dlg->addButtonBox(); if (need_modal) { ptr->setFocus(); dlg->exec(); delete dlg; return; } else { m_Data->m_DiffBrowserPtr = ptr; m_Data->m_DiffDialog = dlg; } } else { m_Data->m_DiffBrowserPtr->setText(ex); m_Data->m_DiffBrowserPtr->setFocus(); } if (m_Data->m_DiffDialog) { m_Data->m_DiffDialog->show(); m_Data->m_DiffDialog->raise(); } } /*! \fn SvnActions::makeUpdate(const QString&what,const svn::Revision&rev,bool recurse) */ void SvnActions::makeUpdate(const svn::Targets &targets, const svn::Revision &rev, svn::Depth depth) { if (!m_Data->m_CurrentContext) { return; } svn::Revisions ret; stopCheckUpdateThread(); try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Making update"), i18n("Making update - hit Cancel for abort")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); svn::UpdateParameter _params; m_Data->m_SvnContextListener->cleanUpdatedItems(); _params.targets(targets).revision(rev).depth(depth).ignore_externals(false).allow_unversioned(false).sticky_depth(true); ret = m_Data->m_Svnclient->update(_params); } catch (const svn::Exception &e) { emit clientException(e.msg()); return; } removeFromUpdateCache(m_Data->m_SvnContextListener->updatedItems(), true); //removeFromUpdateCache(what,depth==svn::DepthFiles); EMIT_REFRESH; EMIT_FINISHED; m_Data->clearCaches(); } /*! \fn SvnActions::slotUpdateHeadRec() */ void SvnActions::slotUpdateHeadRec() { prepareUpdate(false); } /*! \fn SvnActions::prepareUpdate(bool ask) */ void SvnActions::prepareUpdate(bool ask) { if (!m_Data->m_ParentList || !m_Data->m_ParentList->isWorkingCopy()) { return; } const SvnItemList k = m_Data->m_ParentList->SelectionList(); svn::Paths what; if (k.isEmpty()) { what.append(svn::Path(m_Data->m_ParentList->baseUri())); } else { what.reserve(k.size()); Q_FOREACH(const SvnItem *item, k) { what.append(svn::Path(item->fullName())); } } svn::Revision r(svn::Revision::HEAD); if (ask) { Rangeinput_impl::revision_range range; if (!Rangeinput_impl::getRevisionRange(range, true, true)) { return; } r = range.first; } makeUpdate(svn::Targets(what), r, svn::DepthUnknown); } /*! \fn SvnActions::slotUpdateTo() */ void SvnActions::slotUpdateTo() { prepareUpdate(true); } /*! \fn SvnActions::slotAdd() */ void SvnActions::slotAdd() { makeAdd(false); } void SvnActions::slotAddRec() { makeAdd(true); } void SvnActions::makeAdd(bool rec) { if (!m_Data->m_CurrentContext) { return; } if (!m_Data->m_ParentList) { return; } const SvnItemList lst = m_Data->m_ParentList->SelectionList(); if (lst.isEmpty()) { KMessageBox::error(m_Data->m_ParentList->realWidget(), i18n("Which files or directories should I add?")); return; } svn::Paths items; items.reserve(lst.size()); Q_FOREACH(const SvnItem *cur, lst) { if (cur->isVersioned()) { KMessageBox::error(m_Data->m_ParentList->realWidget(), i18n("
The entry
%1
is versioned - break.
", cur->fullName())); return; } items.push_back(svn::Path(cur->fullName())); } addItems(items, (rec ? svn::DepthInfinity : svn::DepthEmpty)); - emit sigRefreshCurrent(0); + emit sigRefreshCurrent(nullptr); } bool SvnActions::addItems(const svn::Paths &items, svn::Depth depth) { try { svn::Paths::const_iterator piter; for (piter = items.begin(); piter != items.end(); ++piter) { m_Data->m_Svnclient->add((*piter), depth); } } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } return true; } bool SvnActions::makeDelete(const QStringList &w) { - KMessageBox::ButtonCode answer = KMessageBox::questionYesNoList(0, + KMessageBox::ButtonCode answer = KMessageBox::questionYesNoList(nullptr, i18n("Really delete these entries?"), w, i18n("Delete from repository")); if (answer != KMessageBox::Yes) { return false; } return makeDelete(svn::Targets::fromStringList(w)); } /*! \fn SvnActions::makeDelete() */ bool SvnActions::makeDelete(const svn::Targets &target, bool keep_local, bool force) { if (!m_Data->m_CurrentContext) { return false; } try { m_Data->m_Svnclient->remove(target, force, keep_local); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } EMIT_FINISHED; return true; } void SvnActions::slotCheckout() { CheckoutExport(QUrl(), false); } void SvnActions::slotExport() { CheckoutExport(QUrl(), true); } void SvnActions::slotCheckoutCurrent() { CheckoutExportCurrent(false); } void SvnActions::slotExportCurrent() { CheckoutExportCurrent(true); } void SvnActions::CheckoutExport(const QUrl &what, bool _exp, bool urlisTarget) { QPointer dlg(new KSvnSimpleOkDialog(QStringLiteral("checkout_export_dialog"))); CheckoutInfo_impl *ptr(new CheckoutInfo_impl(dlg)); dlg->setWindowTitle(_exp ? i18nc("@title:window", "Export a Repository") : i18nc("@title:window", "Checkout a Repository")); dlg->setWithCancelButton(); if (!what.isEmpty()) { if (!urlisTarget) { ptr->setStartUrl(what); } else { ptr->setTargetUrl(what); } } ptr->hideIgnoreKeywords(!_exp); ptr->hideOverwrite(!_exp); dlg->addWidget(ptr); if (dlg->exec() == QDialog::Accepted) { svn::Revision r = ptr->toRevision(); bool openit = ptr->openAfterJob(); bool ignoreExternal = ptr->ignoreExternals(); if (!ptr->reposURL().isValid()) { KMessageBox::error(QApplication::activeModalWidget(), i18n("Invalid url given!"), _exp ? i18n("Export repository") : i18n("Checkout a repository")); delete dlg; return; } // svn::Path should not take a QString but a QByteArray ... const QString rUrl(QString::fromUtf8(ptr->reposURL().toEncoded())); makeCheckout(rUrl, ptr->targetDir(), r, r, ptr->getDepth(), _exp, openit, ignoreExternal, ptr->overwrite(), ptr->ignoreKeywords(), - 0); + nullptr); } delete dlg; } void SvnActions::CheckoutExportCurrent(bool _exp) { // checkout export only on repo, not wc if (!m_Data->m_ParentList || m_Data->m_ParentList->isWorkingCopy()) { return; } SvnItem *k = m_Data->m_ParentList->Selected(); if (k && !k->isDir()) { KMessageBox::error(m_Data->m_ParentList->realWidget(), _exp ? i18n("Exporting a file?") : i18n("Checking out a file?")); return; } QUrl what; if (!k) { what = QUrl(m_Data->m_ParentList->baseUri()); } else { what = QUrl(k->fullName()); } // what is always remote, so QUrl(what) is fine CheckoutExport(QUrl(what), _exp); } bool SvnActions::makeCheckout(const QString &rUrl, const QString &tPath, const svn::Revision &r, const svn::Revision &_peg, svn::Depth depth, // kind of operation bool _exp, // open after job bool openIt, // ignore externals bool ignoreExternal, // overwrite/force not versioned items bool overwrite, // do not replace svn:keywords on export bool ignoreKeywords, QWidget *_p ) { QString fUrl = rUrl; while (fUrl.endsWith(QLatin1Char('/'))) { fUrl.chop(1); } // can only be a local target dir svn::Path p(tPath); svn::Revision peg = _peg; if (r != svn::Revision::BASE && r != svn::Revision::WORKING && _peg == svn::Revision::UNDEFINED) { peg = r; } if (!_exp || !m_Data->m_CurrentContext) { reInitClient(); } svn::CheckoutParameter cparams; cparams.moduleName(fUrl).destination(p).revision(r).peg(peg).depth(depth).ignoreExternals(ignoreExternal).overWrite(overwrite).ignoreKeywords(ignoreKeywords); try { StopDlg sdlg(m_Data->m_SvnContextListener, _p ? _p : m_Data->m_ParentList->realWidget(), _exp ? i18nc("@title:window", "Export") : i18nc("@title:window", "Checkout"), _exp ? i18n("Exporting") : i18n("Checking out")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); if (_exp) { /// @todo setup parameter for export operation m_Data->m_Svnclient->doExport(cparams.nativeEol(QString())); } else { m_Data->m_Svnclient->checkout(cparams); } } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } if (openIt) { const QUrl url(QUrl::fromLocalFile(tPath)); if (!_exp) { emit sigGotourl(url); } else { QDesktopServices::openUrl(url); } } EMIT_FINISHED; return true; } void SvnActions::slotRevert() { if (!m_Data->m_ParentList || !m_Data->m_ParentList->isWorkingCopy()) { return; } const SvnItemList lst = m_Data->m_ParentList->SelectionList(); QStringList displist; if (!lst.isEmpty()) { displist.reserve(lst.size()); Q_FOREACH(const SvnItem *cur, lst) { if (!cur->isVersioned()) { KMessageBox::error(m_Data->m_ParentList->realWidget(), i18n("
The entry
%1
is not versioned - break.
", cur->fullName())); return; } displist.append(cur->fullName()); } } else { displist.push_back(m_Data->m_ParentList->baseUri()); } slotRevertItems(displist); EMIT_REFRESH; } void SvnActions::slotRevertItems(const QStringList &displist) { if (!m_Data->m_CurrentContext) { return; } if (displist.isEmpty()) { return; } QPointer dlg(new RevertForm(displist, QApplication::activeModalWidget())); if (dlg->exec() != QDialog::Accepted) { delete dlg; return; } const svn::Depth depth = dlg->getDepth(); delete dlg; const svn::Targets target(svn::Targets::fromStringList(displist)); try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Revert"), i18n("Reverting items")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); m_Data->m_Svnclient->revert(target, depth); } catch (const svn::Exception &e) { emit clientException(e.msg()); return; } // remove them from cache for (size_t j = 0; j < target.size(); ++j) { m_Data->m_Cache.deleteKey(target[j].path(), depth != svn::DepthInfinity); } emit sigItemsReverted(displist); EMIT_FINISHED; } bool SvnActions::makeSwitch(const QUrl &rUrl, const QString &tPath, const svn::Revision &r, svn::Depth depth, const svn::Revision &peg, bool stickydepth, bool ignore_externals, bool allow_unversioned) { if (!m_Data->m_CurrentContext) { return false; } svn::Path p(tPath); try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Switch URL"), i18n("Switching URL")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); m_Data->m_Svnclient->doSwitch(p, svn::Url(rUrl), r, depth, peg, stickydepth, ignore_externals, allow_unversioned); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } m_Data->clearCaches(); EMIT_FINISHED; return true; } bool SvnActions::makeRelocate(const QUrl &fUrl, const QUrl &tUrl, const QString &path, bool recursive, bool ignore_externals) { if (!m_Data->m_CurrentContext) { return false; } svn::Path p(path); try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Relocate Repository"), i18n("Relocate repository to new URL")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); m_Data->m_Svnclient->relocate(p, svn::Url(fUrl), svn::Url(tUrl), recursive, ignore_externals); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } m_Data->clearCaches(); EMIT_FINISHED; return true; } void SvnActions::slotSwitch() { if (!m_Data->m_CurrentContext) { return; } if (!m_Data->m_ParentList || !m_Data->m_ParentList->isWorkingCopy()) { return; } const SvnItemList lst = m_Data->m_ParentList->SelectionList(); if (lst.count() > 1) { - KMessageBox::error(0, i18n("Can only switch one item at time")); + KMessageBox::error(nullptr, i18n("Can only switch one item at time")); return; } SvnItem *k = m_Data->m_ParentList->SelectedOrMain(); if (!k) { - KMessageBox::error(0, i18n("Error getting entry to switch")); + KMessageBox::error(nullptr, i18n("Error getting entry to switch")); return; } const QUrl what = k->Url(); if (makeSwitch(k->fullName(), what)) { emit reinitItem(k); } } bool SvnActions::makeSwitch(const QString &path, const QUrl &what) { QPointer dlg(new KSvnSimpleOkDialog(QStringLiteral("switch_url_dlg"))); CheckoutInfo_impl *ptr(new CheckoutInfo_impl(dlg)); dlg->setWindowTitle(i18nc("@title:window", "Switch URL")); dlg->setWithCancelButton(); ptr->setStartUrl(what); ptr->disableAppend(true); ptr->disableTargetDir(true); ptr->disableOpen(true); dlg->addWidget(ptr); bool done = false; if (dlg->exec() == QDialog::Accepted) { if (!ptr->reposURL().isValid()) { KMessageBox::error(QApplication::activeModalWidget(), i18n("Invalid url given!"), i18n("Switch URL")); delete dlg; return false; } svn::Revision r = ptr->toRevision(); done = makeSwitch(ptr->reposURL(), path, r, ptr->getDepth(), r, true, ptr->ignoreExternals(), ptr->overwrite()); } delete dlg; return done; } bool SvnActions::makeCleanup(const QString &path) { if (!m_Data->m_CurrentContext) { return false; } try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Cleanup"), i18n("Cleaning up folder")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); m_Data->m_Svnclient->cleanup(svn::Path(path)); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } return true; } void SvnActions::slotResolved(const QString &path) { if (!m_Data->m_CurrentContext) { return; } try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Resolve"), i18n("Marking resolved")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); m_Data->m_Svnclient->resolve(svn::Path(path), svn::DepthEmpty); } catch (const svn::Exception &e) { emit clientException(e.msg()); return; } m_Data->m_conflictCache.deleteKey(path, false); } void SvnActions::slotResolve(const QString &p) { if (!m_Data->m_CurrentContext) { return; } const QString eresolv = Kdesvnsettings::conflict_resolver(); const QVector wlist = eresolv.splitRef(QLatin1Char(' ')); if (wlist.isEmpty()) { return; } svn::InfoEntry i1; if (!singleInfo(p, svn::Revision::UNDEFINED, i1)) { return; } QFileInfo fi(p); QString base; if (fi.isRelative()) { base = fi.absolutePath() + QLatin1Char('/'); } if (i1.conflicts().isEmpty()) { emit sendNotify(i18n("Could not retrieve conflict information - giving up.")); return; } WatchedProcess *proc = new WatchedProcess(this); for (auto it = wlist.begin(); it != wlist.end(); ++it) { if (*it == QLatin1String("%o") || *it == QLatin1String("%l")) { *proc << i1.conflicts()[0]->baseFile(); } else if (*it == QLatin1String("%m") || *it == QLatin1String("%w")) { *proc << i1.conflicts()[0]->myFile(); } else if (*it == QLatin1String("%n") || *it == QLatin1String("%r")) { *proc << i1.conflicts()[0]->theirFile(); } else if (*it == QLatin1String("%t")) { *proc << p; } else { *proc << (*it).toString(); } } proc->setAutoDelete(true); proc->setOutputChannelMode(KProcess::MergedChannels); connect(proc, SIGNAL(dataStderrRead(QByteArray,WatchedProcess*)), this, SLOT(slotProcessDataRead(QByteArray,WatchedProcess*))); connect(proc, SIGNAL(dataStdoutRead(QByteArray,WatchedProcess*)), this, SLOT(slotProcessDataRead(QByteArray,WatchedProcess*))); proc->start(); if (!proc->waitForStarted(-1)) { emit sendNotify(i18n("Resolve-process could not started, check command.")); } } void SvnActions::slotImport(const QString &path, const QUrl &target, const QString &message, svn::Depth depth, bool noIgnore, bool noUnknown) { if (!m_Data->m_CurrentContext) { return; } try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Import"), i18n("Importing items")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); m_Data->m_Svnclient->import(svn::Path(path), svn::Url(target), message, depth, noIgnore, noUnknown); } catch (const svn::Exception &e) { emit clientException(e.msg()); return; } } void SvnActions::slotMergeExternal(const QString &_src1, const QString &_src2, const QString &_target, const svn::Revision &rev1, const svn::Revision &rev2, const svn::Revision &_peg, bool rec) { Q_UNUSED(_peg); QTemporaryDir tdir1; tdir1.setAutoRemove(true); QString src1 = _src1; QString src2 = _src2; QString target = _target; bool singleMerge = false; if (rev1 == rev2 && (src2.isEmpty() || src1 == src2)) { singleMerge = true; } if (src1.isEmpty()) { emit clientException(i18n("Nothing to merge.")); return; } if (target.isEmpty()) { emit clientException(i18n("No destination to merge.")); return; } QFileInfo f1(src1); QFileInfo f2(src2); bool isDir = true; svn::InfoEntry i1, i2; if (!singleInfo(src1, rev1, i1)) { return; } isDir = i1.isDir(); if (!singleMerge && src1 != src2) { if (!singleInfo(src2, rev2, i2)) { return; } if (i2.isDir() != isDir) { emit clientException(i18n("Both sources must be same type.")); return; } } QFileInfo ti(target); if (ti.isDir() != isDir) { emit clientException(i18n("Target for merge must same type like sources.")); return; } QString s1 = f1.fileName() + QLatin1Char('-') + rev1.toString(); QString s2 = f2.fileName() + QLatin1Char('-') + rev2.toString(); QString first, second; if (rev1 != svn::Revision::WORKING) { first = tdir1.path() + QLatin1Char('/') + s1; } else { first = src1; } if (!singleMerge) { if (rev2 != svn::Revision::WORKING) { second = tdir1.path() + QLatin1Char('/') + s2; } else { second = src2; } } else { // only two-way merge second.clear(); } if (second == first) { KMessageBox::error(m_Data->m_ParentList->realWidget(), i18n("Both entries seems to be the same, will not do a merge.")); return; } if (rev1 != svn::Revision::WORKING) { if (isDir) { if (!makeCheckout(src1, first, rev1, svn::Revision::UNDEFINED, rec ? svn::DepthInfinity : svn::DepthFiles, - true, false, false, false, false, 0)) { + true, false, false, false, false, nullptr)) { return; } } else { if (!get(src1, first, rev1, svn::Revision::UNDEFINED, m_Data->m_ParentList->realWidget())) { return; } } } if (!singleMerge) { if (rev2 != svn::Revision::WORKING) { if (isDir) { if (!makeCheckout(src2, second, rev2, svn::Revision::UNDEFINED, rec ? svn::DepthInfinity : svn::DepthFiles, - true, false, false, false, false, 0)) { + true, false, false, false, false, nullptr)) { return; } } else { if (!get(src2, second, rev2, svn::Revision::UNDEFINED, m_Data->m_ParentList->realWidget())) { return; } } } } const QString edisp = Kdesvnsettings::external_merge_program(); const QVector wlist = edisp.splitRef(QLatin1Char(' ')); WatchedProcess *proc = new WatchedProcess(this); for (auto it = wlist.begin(); it != wlist.end(); ++it) { if (*it == QLatin1String("%s1")) { *proc << first; } else if (*it == QLatin1String("%s2")) { if (!second.isEmpty()) { *proc << second; } } else if (*it == QLatin1String("%t")) { *proc << target; } else { *proc << (*it).toString(); } } tdir1.setAutoRemove(false); proc->setAutoDelete(true); proc->appendTempDir(tdir1.path()); proc->setOutputChannelMode(KProcess::MergedChannels); connect(proc, SIGNAL(dataStderrRead(QByteArray,WatchedProcess*)), this, SLOT(slotProcessDataRead(QByteArray,WatchedProcess*))); connect(proc, SIGNAL(dataStdoutRead(QByteArray,WatchedProcess*)), this, SLOT(slotProcessDataRead(QByteArray,WatchedProcess*))); proc->start(); if (proc->waitForStarted(-1)) { if (m_Data->runblocked) { proc->waitForFinished(-1); } } else { emit sendNotify(i18n("Merge process could not started, check command.")); } } void SvnActions::slotMergeWcRevisions(const QString &_entry, const svn::Revision &rev1, const svn::Revision &rev2, bool rec, bool ancestry, bool forceIt, bool dry, bool allow_mixed_rev) { slotMerge(_entry, _entry, _entry, rev1, rev2, svn::Revision::UNDEFINED, rec, ancestry, forceIt, dry, false, false, allow_mixed_rev); } void SvnActions::slotMerge(const QString &src1, const QString &src2, const QString &target, const svn::Revision &rev1, const svn::Revision &rev2, const svn::Revision &_peg, bool rec, bool ancestry, bool forceIt, bool dry, bool recordOnly, bool reintegrate, bool allow_mixed_rev) { Q_UNUSED(_peg); if (!m_Data->m_CurrentContext) { return; } svn::Revision peg = svn::Revision::HEAD; svn::Revision tpeg; svn::RevisionRanges ranges; svn::Path p1; try { svn::Path::parsePeg(src1, p1, tpeg); } catch (const svn::Exception &e) { emit clientException(e.msg()); return; } if (tpeg != svn::Revision::UNDEFINED) { peg = tpeg; } svn::Path p2(src2); bool pegged_merge = false; // build merge Parameters svn::MergeParameter _merge_parameter; ranges.append(svn::RevisionRange(rev1, rev2)); _merge_parameter.revisions(ranges).path1(p1).path2(p2).depth(rec ? svn::DepthInfinity : svn::DepthFiles).notice_ancestry(ancestry).force(forceIt) .dry_run(dry).record_only(recordOnly).reintegrate(reintegrate).allow_mixed_rev(allow_mixed_rev) .localPath(svn::Path(target)).merge_options(svn::StringArray()); if (!reintegrate && (!p2.isSet() || src1 == src2)) { // pegged merge pegged_merge = true; if (peg == svn::Revision::UNDEFINED) { if (p1.isUrl()) { peg = rev2; } else { peg = svn::Revision::WORKING; } } _merge_parameter.peg(peg); } try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Merge"), i18n("Merging items")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); if (pegged_merge) { m_Data->m_Svnclient->merge_peg(_merge_parameter); } else { m_Data->m_Svnclient->merge(_merge_parameter); } } catch (const svn::Exception &e) { emit clientException(e.msg()); return; } m_Data->clearCaches(); } /*! \fn SvnActions::slotCopyMove(bool,const QString&,const QString&) */ bool SvnActions::makeMove(const QString &Old, const QString &New) { if (!m_Data->m_CurrentContext) { return false; } svn::CopyParameter params(Old, New); svn::Revision nnum; try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Move"), i18n("Moving/Rename item")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); nnum = m_Data->m_Svnclient->move(params.asChild(false).makeParent(false)); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } if (nnum != svn::Revision::UNDEFINED) { emit sendNotify(i18n("Committed revision %1.", nnum.toString())); } EMIT_REFRESH; return true; } bool SvnActions::makeMove(const QList &Old, const QString &New) { try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Move"), i18n("Moving entries")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); const svn::Path pNew(New); // either both are local paths -> move in wc, or both are urls -> move in repository const svn::Targets t(svn::Targets::fromUrlList(Old, pNew.isUrl() ? svn::Targets::UrlConversion::KeepUrl : svn::Targets::UrlConversion::PreferLocalPath)); m_Data->m_Svnclient->move(svn::CopyParameter(t, pNew).asChild(true).makeParent(false)); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } return true; } bool SvnActions::makeCopy(const QString &Old, const QString &New, const svn::Revision &rev) { if (!m_Data->m_CurrentContext) { return false; } try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Copy / Move"), i18n("Copy or Moving entries")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); m_Data->m_Svnclient->copy(svn::Path(Old), rev, svn::Path(New)); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } EMIT_REFRESH; return true; } bool SvnActions::makeCopy(const QList &Old, const QString &New, const svn::Revision &rev) { try { StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Copy / Move"), i18n("Copy or Moving entries")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); const svn::Path pNew(New); // either both are local paths -> copy in wc, or both are urls -> copy in repository const svn::Targets t(svn::Targets::fromUrlList(Old, pNew.isUrl() ? svn::Targets::UrlConversion::KeepUrl : svn::Targets::UrlConversion::PreferLocalPath)); m_Data->m_Svnclient->copy(svn::CopyParameter(t, pNew).srcRevision(rev).pegRevision(rev).asChild(true)); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } return true; } /*! \fn SvnActions::makeLock(const QStringList&) */ void SvnActions::makeLock(const QStringList &what, const QString &_msg, bool breakit) { if (!m_Data->m_CurrentContext) { return; } try { m_Data->m_Svnclient->lock(svn::Targets::fromStringList(what), _msg, breakit); } catch (const svn::Exception &e) { emit clientException(e.msg()); return; } } /*! \fn SvnActions::makeUnlock(const QStringList&) */ void SvnActions::makeUnlock(const QStringList &what, bool breakit) { if (!m_Data->m_CurrentContext) { return; } try { m_Data->m_Svnclient->unlock(svn::Targets::fromStringList(what), breakit); } catch (const svn::Exception &e) { emit clientException(e.msg()); return; } for (long i = 0; i < what.count(); ++i) { m_Data->m_repoLockCache.deleteKey(what[i], true); } // m_Data->m_repoLockCache.dump_tree(); } /*! \fn SvnActions::makeStatus(const QString&what, svn::StatusEntries&dlist) */ bool SvnActions::makeStatus(const QString &what, svn::StatusEntries &dlist, const svn::Revision &where, bool rec, bool all) { bool display_ignores = Kdesvnsettings::display_ignored_files(); return makeStatus(what, dlist, where, rec, all, display_ignores); } bool SvnActions::makeStatus(const QString &what, svn::StatusEntries &dlist, const svn::Revision &where, bool rec, bool all, bool display_ignores, bool updates) { svn::Depth _d = rec ? svn::DepthInfinity : svn::DepthImmediates; return makeStatus(what, dlist, where, _d, all, display_ignores, updates); } bool SvnActions::makeStatus(const QString &what, svn::StatusEntries &dlist, const svn::Revision &where, svn::Depth _d, bool all, bool display_ignores, bool updates) { bool disp_remote_details = Kdesvnsettings::details_on_remote_listing(); try { #ifdef DEBUG_TIMER QTime _counttime; _counttime.start(); #endif svn::StatusParameter params(what); StopDlg sdlg(m_Data->m_SvnContextListener, m_Data->m_ParentList->realWidget(), i18nc("@title:window", "Status / List"), i18n("Creating list / check status")); connect(this, SIGNAL(sigExtraLogMsg(QString)), &sdlg, SLOT(slotExtraMessage(QString))); // rec all up noign dlist = m_Data->m_Svnclient->status(params.depth(_d).all(all).update(updates).noIgnore(display_ignores).revision(where).detailedRemote(disp_remote_details).ignoreExternals(false)); #ifdef DEBUG_TIMER qCDebug(KDESVN_LOG) << "Time for getting status: " << _counttime.elapsed(); #endif } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } return true; } void SvnActions::checkAddItems(const QString &path, bool print_error_box) { svn::StatusEntries dlist; svn::StatusEntries rlist; QStringList displist; svn::Revision where = svn::Revision::HEAD; if (!makeStatus(path, dlist, where, true, true, false, false)) { return; } for (int i = 0; i < dlist.size(); ++i) { const svn::StatusPtr &ptr = dlist.at(i); if (!ptr->isVersioned()) { rlist.append(ptr); displist.append(ptr->path()); } } if (rlist.isEmpty()) { if (print_error_box) { KMessageBox::error(m_Data->m_ParentList->realWidget(), i18n("No unversioned items found.")); } } else { QPointer dlg(new KSvnSimpleOkDialog(QStringLiteral("add_items_dlg"))); dlg->setWindowTitle(i18nc("@title:window", "Add Unversioned Items")); dlg->setWithCancelButton(); QTreeWidget *ptr(new QTreeWidget(dlg)); ptr->headerItem()->setText(0, i18n("Item")); for (int j = 0; j < displist.size(); ++j) { QTreeWidgetItem *n = new QTreeWidgetItem(ptr); n->setText(0, displist[j]); n->setCheckState(0, Qt::Checked); } ptr->resizeColumnToContents(0); dlg->addWidget(ptr); if (dlg->exec() == QDialog::Accepted) { QTreeWidgetItemIterator it(ptr); displist.clear(); while (*it) { QTreeWidgetItem *t = (*it); if (t->checkState(0) == Qt::Checked) { displist.append(t->text(0)); } ++it; } if (!displist.isEmpty()) { addItems(svn::Targets::fromStringList(displist).targets(), svn::DepthEmpty); } } delete dlg; } } void SvnActions::stopCheckModifiedThread() { if (m_CThread) { m_CThread->cancelMe(); if (!m_CThread->wait(MAX_THREAD_WAITTIME)) { m_CThread->terminate(); m_CThread->wait(MAX_THREAD_WAITTIME); } delete m_CThread; m_CThread = nullptr; } } void SvnActions::stopCheckUpdateThread() { if (m_UThread) { m_UThread->cancelMe(); if (!m_UThread->wait(MAX_THREAD_WAITTIME)) { m_UThread->terminate(); m_UThread->wait(MAX_THREAD_WAITTIME); } delete m_UThread; m_UThread = nullptr; } } void SvnActions::stopFillCache() { if (m_FCThread) { m_FCThread->cancelMe(); if (!m_FCThread->wait(MAX_THREAD_WAITTIME)) { m_FCThread->terminate(); m_FCThread->wait(MAX_THREAD_WAITTIME); } delete m_FCThread; m_FCThread = nullptr; emit sigThreadsChanged(); emit sigCacheStatus(-1, -1); } } void SvnActions::stopMain() { if (m_Data->m_CurrentContext) { m_Data->m_SvnContextListener->setCanceled(true); sleep(1); m_Data->m_SvnContextListener->contextCancel(); } } void SvnActions::killallThreads() { stopMain(); stopCheckModifiedThread(); stopCheckUpdateThread(); stopFillCache(); } bool SvnActions::createModifiedCache(const QString &what) { stopCheckModifiedThread(); m_CThread = new CheckModifiedThread(this, what, false); connect(m_CThread, SIGNAL(checkModifiedFinished()), this, SLOT(checkModifiedThread())); m_CThread->start(); return true; } void SvnActions::checkModifiedThread() { if (!m_CThread) { return; } if (m_CThread->isRunning()) { QTimer::singleShot(2, this, SLOT(checkModifiedThread())); return; } m_Data->m_Cache.clear(); m_Data->m_conflictCache.clear(); const svn::StatusEntries &sEntries = m_CThread->getList(); for (int i = 0; i < sEntries.size(); ++i) { const svn::StatusPtr ptr = sEntries.at(i); if (ptr->isRealVersioned() && ( ptr->nodeStatus() == svn_wc_status_modified || ptr->nodeStatus() == svn_wc_status_added || ptr->nodeStatus() == svn_wc_status_deleted || ptr->nodeStatus() == svn_wc_status_replaced || ptr->nodeStatus() == svn_wc_status_modified )) { m_Data->m_Cache.insertKey(ptr, ptr->path()); } else if (ptr->nodeStatus() == svn_wc_status_conflicted) { m_Data->m_conflictCache.insertKey(ptr, ptr->path()); } } sigExtraStatusMessage(i18np("Found %1 modified item", "Found %1 modified items", sEntries.size())); delete m_CThread; m_CThread = nullptr; emit sigCacheDataChanged(); emit sigRefreshIcons(); } void SvnActions::checkUpdateThread() { if (!m_UThread || m_UThread->isRunning()) { if (m_UThread) { QTimer::singleShot(2, this, SLOT(checkUpdateThread())); } return; } bool newer = false; const svn::StatusEntries &sEntries = m_UThread->getList(); for (int i = 0; i < sEntries.size(); ++i) { const svn::StatusPtr ptr = sEntries.at(i); if (ptr->validReposStatus()) { m_Data->m_UpdateCache.insertKey(ptr, ptr->path()); if (!(ptr->validLocalStatus())) { newer = true; } } if (ptr->isLocked() && !(ptr->entry().lockEntry().Locked())) { m_Data->m_repoLockCache.insertKey(ptr, ptr->path()); } } emit sigRefreshIcons(); emit sigExtraStatusMessage(i18n("Checking for updates finished")); if (newer) { emit sigExtraStatusMessage(i18n("There are new items in repository")); } delete m_UThread; m_UThread = nullptr; emit sigCacheDataChanged(); } void SvnActions::getaddedItems(const QString &path, svn::StatusEntries &target) { helpers::ValidRemoteOnly vro; m_Data->m_UpdateCache.listsubs_if(path, vro); target = vro.liste(); } bool SvnActions::checkUpdatesRunning() { return m_UThread && m_UThread->isRunning(); } void SvnActions::addModifiedCache(const svn::StatusPtr &what) { if (what->nodeStatus() == svn_wc_status_conflicted) { m_Data->m_conflictCache.insertKey(what, what->path()); } else { m_Data->m_Cache.insertKey(what, what->path()); } } void SvnActions::deleteFromModifiedCache(const QString &what) { m_Data->m_Cache.deleteKey(what, true); m_Data->m_conflictCache.deleteKey(what, true); //m_Data->m_Cache.dump_tree(); } bool SvnActions::checkModifiedCache(const QString &path) const { return m_Data->m_Cache.find(path); } bool SvnActions::checkReposLockCache(const QString &path) const { return m_Data->m_repoLockCache.findSingleValid(path, false); } bool SvnActions::checkReposLockCache(const QString &path, svn::StatusPtr &t) const { /// @todo create a method where svn::Status* will be a parameter so no copy is needed but just reading content return m_Data->m_repoLockCache.findSingleValid(path, t); } bool SvnActions::checkConflictedCache(const QString &path) const { return m_Data->m_conflictCache.find(path); } void SvnActions::startFillCache(const QString &path, bool startup) { #ifdef DEBUG_TIMER QTime _counttime; _counttime.start(); #endif stopFillCache(); #ifdef DEBUG_TIMER qCDebug(KDESVN_LOG) << "Stopped cache " << _counttime.elapsed(); _counttime.restart(); #endif if (!doNetworking()) { emit sendNotify(i18n("Not filling log cache because networking is disabled")); return; } m_FCThread = new FillCacheThread(this, path, startup); connect(m_FCThread, SIGNAL(fillCacheStatus(qlonglong,qlonglong)), this, SIGNAL(sigCacheStatus(qlonglong,qlonglong))); connect(m_FCThread, SIGNAL(fillCacheFinished()), this, SLOT(stopFillCache())); m_FCThread->start(); } bool SvnActions::doNetworking() { // if networking is allowd we don't need extra checks, second is just for avoiding segfaults if (Kdesvnsettings::network_on() || !m_Data->m_ParentList) { return true; } bool is_url = false; if (m_Data->m_ParentList->isNetworked()) { // if called http:// etc.pp. is_url = true; } else if (m_Data->m_ParentList->baseUri().startsWith(QLatin1Char('/'))) { // if opened a working copy we must check if it points to a networking repository svn::InfoEntry e; if (!singleInfo(m_Data->m_ParentList->baseUri(), svn::Revision::UNDEFINED, e)) { return false; } is_url = !e.reposRoot().isLocalFile(); } return !is_url; } /*! \fn SvnActions::createUpdateCache(const QString&what) */ bool SvnActions::createUpdateCache(const QString &what) { clearUpdateCache(); m_Data->m_repoLockCache.clear(); stopCheckUpdateThread(); if (!doNetworking()) { emit sigExtraStatusMessage(i18n("Not checking for updates because networking is disabled")); return false; } m_UThread = new CheckModifiedThread(this, what, true); connect(m_UThread, SIGNAL(checkModifiedFinished()), this, SLOT(checkUpdateThread())); m_UThread->start(); emit sigExtraStatusMessage(i18n("Checking for updates started in background")); return true; } bool SvnActions::checkUpdateCache(const QString &path)const { return m_Data->m_UpdateCache.find(path); } void SvnActions::removeFromUpdateCache(const QStringList &what, bool exact_only) { for (int i = 0; i < what.size(); ++i) { m_Data->m_UpdateCache.deleteKey(what.at(i), exact_only); } } bool SvnActions::isUpdated(const QString &path)const { svn::StatusPtr d; return getUpdated(path, d); } bool SvnActions::getUpdated(const QString &path, svn::StatusPtr &d)const { return m_Data->m_UpdateCache.findSingleValid(path, d); } void SvnActions::clearUpdateCache() { m_Data->m_UpdateCache.clear(); } bool SvnActions::makeIgnoreEntry(const svn::Path &item, const QStringList &ignorePattern, bool unignore) { svn::Revision r(svn::Revision::UNDEFINED); QPair pmp; try { pmp = m_Data->m_Svnclient->propget(QStringLiteral("svn:ignore"), item, r, r); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } svn::PathPropertiesMapList pm = pmp.second; QString data; if (!pm.isEmpty()) { const svn::PropertiesMap &mp = pm[0].second; data = mp[QStringLiteral("svn:ignore")]; } bool result = false; QStringList lst = data.split(QLatin1Char('\n'), QString::SkipEmptyParts); for (int _current = 0; _current < ignorePattern.size(); ++_current) { int it = lst.indexOf(ignorePattern[_current]); if (it != -1) { if (unignore) { lst.removeAt(it); result = true; } } else { if (!unignore) { lst.append(ignorePattern[_current]); result = true; } } } if (result) { data = lst.join(QLatin1Char('\n')); try { m_Data->m_Svnclient->propset(svn::PropertiesParameter().propertyName(QStringLiteral("svn:ignore")).propertyValue(data).path(item)); } catch (const svn::Exception &e) { emit clientException(e.msg()); return false; } } return result; } bool SvnActions::makeIgnoreEntry(SvnItem *which, bool unignore) { if (!which) { return false; } QString parentName = which->getParentDir(); if (parentName.isEmpty()) { return false; } QString name = which->shortName(); return makeIgnoreEntry(svn::Path(parentName), QStringList(name), unignore); } svn::PathPropertiesMapListPtr SvnActions::propList(const QString &which, const svn::Revision &where, bool cacheOnly) { svn::PathPropertiesMapListPtr pm; if (!which.isEmpty()) { QString fk = where.toString() + QLatin1Char('/') + which; svn::Path p(which); if (where != svn::Revision::WORKING) { m_Data->m_PropertiesCache.findSingleValid(fk, pm); } if (!pm && !cacheOnly) { try { pm = m_Data->m_Svnclient->proplist(p, where, where); } catch (const svn::Exception &e) { /* no messagebox needed */ if (e.apr_err() != SVN_ERR_WC_NOT_DIRECTORY) { sendNotify(e.msg()); } } if (where != svn::Revision::WORKING && pm) { m_Data->m_PropertiesCache.insertKey(pm, fk); } } } return pm; } bool SvnActions::isLockNeeded(SvnItem *which, const svn::Revision &where) { if (!which) { return false; } svn::Path p(which->fullName()); QPair pmp; try { pmp = m_Data->m_Svnclient->propget(QStringLiteral("svn:needs-lock"), p, where, where); } catch (const svn::Exception &e) { /* no messagebox needed */ //emit clientException(e.msg()); return false; } const svn::PathPropertiesMapList pm = pmp.second; if (!pm.isEmpty()) { const svn::PropertiesMap &mp = pm.at(0).second; if (mp.contains(QStringLiteral("svn:needs-lock"))) { return true; } } return false; } QString SvnActions::searchProperty(QString &Store, const QString &property, const QString &start, const svn::Revision &where, bool up) { svn::Path pa(start); svn::InfoEntry inf; if (!singleInfo(start, where, inf)) { return QString(); } while (pa.length() > 0) { const svn::PathPropertiesMapListPtr pm = propList(pa.path(), where, false); if (!pm) { return QString(); } if (!pm->isEmpty()) { const svn::PropertiesMap &mp = pm->at(0).second; const svn::PropertiesMap::ConstIterator it = mp.find(property); if (it != mp.end()) { Store = *it; return pa.path(); } } if (up) { pa.removeLast(); if (pa.isUrl() && inf.reposRoot().toString().length() > pa.path().length()) { break; } } else { break; } } return QString(); } bool SvnActions::makeList(const QString &url, svn::DirEntries &dlist, const svn::Revision &where, svn::Depth depth) { if (!m_Data->m_CurrentContext) { return false; } try { dlist = m_Data->m_Svnclient->list(url, where, where, depth, false); } catch (const svn::Exception &e) { qCDebug(KDESVN_LOG) << "List fehler: " << e.msg(); emit clientException(e.msg()); return false; } return true; } bool SvnActions::isLocalWorkingCopy(const QString &path, QUrl &repoUrl) { if (path.isEmpty()) { return false; } const QUrl url = helpers::KTranslateUrl::string2Uri(path); if (!url.isLocalFile()) { qCDebug(KDESVN_LOG) << "isLocalWorkingCopy no local file: " << path << " - " << url.toString(); return false; } QString cleanpath = url.adjusted(QUrl::StripTrailingSlash|QUrl::NormalizePathSegments).path(); qCDebug(KDESVN_LOG) << "isLocalWorkingCopy for " << cleanpath; repoUrl.clear(); svn::Revision peg(svn_opt_revision_unspecified); svn::Revision rev(svn_opt_revision_unspecified); svn::InfoEntries e; try { e = m_Data->m_Svnclient->info(cleanpath, svn::DepthEmpty, rev, peg); } catch (const svn::Exception &e) { if (SVN_ERR_WC_NOT_DIRECTORY == e.apr_err()) { return false; } return true; } if (!e.isEmpty()) repoUrl = e.at(0).url(); return true; } void SvnActions::slotExtraLogMsg(const QString &msg) { emit sigExtraLogMsg(msg); } void SvnActions::slotCancel(bool how) { if (!m_Data->m_CurrentContext) { return; } m_Data->m_SvnContextListener->setCanceled(how); } void SvnActions::setContextData(const QString &aKey, const QString &aValue) { if (aValue.isNull()) { QMap::iterator it = m_Data->m_contextData.find(aKey); if (it != m_Data->m_contextData.end()) { m_Data->m_contextData.remove(aKey); } } else { m_Data->m_contextData[aKey] = aValue; } } void SvnActions::clearContextData() { m_Data->m_contextData.clear(); } QString SvnActions::getContextData(const QString &aKey)const { if (m_Data->m_contextData.find(aKey) != m_Data->m_contextData.end()) { return m_Data->m_contextData[aKey]; } return QString(); } bool SvnActions::threadRunning(ThreadType which) const { switch (which) { case checkupdatethread: return (m_UThread && m_UThread->isRunning()); case fillcachethread: return (m_FCThread && m_FCThread->isRunning()); case checkmodifiedthread: return (m_CThread && m_CThread->isRunning()); } return false; } diff --git a/src/svnfrontend/svnactions.h b/src/svnfrontend/svnactions.h index 3a21f80e..8a691539 100644 --- a/src/svnfrontend/svnactions.h +++ b/src/svnfrontend/svnactions.h @@ -1,248 +1,248 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef SVNACTIONS_H #define SVNACTIONS_H #include "svnqt/client.h" #include "svnqt/revision.h" #include "svnqt/svnqttypes.h" #include "simple_logcb.h" #include "frontendtypes.h" #include #include #include class ItemDisplay; class SvnItem; class QDialog; class CContextListener; class SvnActionsData; class CheckModifiedThread; class CheckUpdatesThread; class FillCacheThread; class WatchedProcess; namespace svn { class LogEntry; class InfoEntry; } namespace KIO { class Job; } /** @author Rajko Albrecht */ class SvnActions : public QObject, public SimpleLogCb { Q_OBJECT public: enum ThreadType { checkupdatethread, fillcachethread, checkmodifiedthread }; explicit SvnActions(ItemDisplay *parent, bool processes_blocked = false); ~SvnActions(); void reInitClient(); svn::ClientP svnclient(); void prepareUpdate(bool ask); bool makeGet(const svn::Revision &start, const QString &what, const QString &target, - const svn::Revision &peg = svn::Revision::UNDEFINED, QWidget *dlgparent = 0); + const svn::Revision &peg = svn::Revision::UNDEFINED, QWidget *dlgparent = nullptr); bool addItems(const svn::Paths &items, svn::Depth depth = svn::DepthEmpty); void checkAddItems(const QString &path, bool print_error_box = true); bool makeDelete(const svn::Targets &target, bool keep_local = true, bool force = false); bool makeDelete(const QStringList &); void makeLock(const QStringList &, const QString &, bool); void makeUnlock(const QStringList &, bool); bool makeStatus(const QString &what, svn::StatusEntries &dlist, const svn::Revision &where, bool rec = false, bool all = true); bool makeStatus(const QString &what, svn::StatusEntries &dlist, const svn::Revision &where, bool rec, bool all, bool display_ignored, bool updates = false); bool makeStatus(const QString &what, svn::StatusEntries &dlist, const svn::Revision &where, svn::Depth depth, bool all, bool display_ignored, bool updates = false); bool makeList(const QString &url, svn::DirEntries &dlist, const svn::Revision &where, svn::Depth depth = svn::DepthInfinity); bool createModifiedCache(const QString &base); bool checkModifiedCache(const QString &path) const; bool checkConflictedCache(const QString &path) const; bool checkReposLockCache(const QString &path) const; bool checkReposLockCache(const QString &path, svn::StatusPtr &t) const; void addModifiedCache(const svn::StatusPtr &what); void deleteFromModifiedCache(const QString &what); bool makeIgnoreEntry(SvnItem *which, bool unignore); bool makeIgnoreEntry(const svn::Path &item, const QStringList &ignorePattern, bool unignore); bool isLockNeeded(SvnItem *which, const svn::Revision &where); QString searchProperty(QString &store, const QString &property, const QString &start, const svn::Revision &where, bool up = false); svn::PathPropertiesMapListPtr propList(const QString &which, const svn::Revision &where, bool cacheOnly); bool changeProperties(const svn::PropertiesMap &setList, const QStringList &, const QString &path, const svn::Depth &depth = svn::DepthEmpty); //! generate and displays a revision tree /*! * the parameter @a what must prepared, eg, if it comes from working copy * it must not contain a "file://" inside. * \param what item to display * \param rev Revision the item-path is available, intersting only when @a what is a repository item * \param startr startrevision for log * \param endr endrevision for log */ void makeTree(const QString &what, const svn::Revision &rev, const svn::Revision &startr = svn::Revision(1), const svn::Revision &endr = svn::Revision::HEAD); void makeLog(const svn::Revision &start, const svn::Revision &end, const svn::Revision &peg, const QString &, bool follow, bool list_files = false, int limit = 0); - svn::LogEntriesMapPtr getLog(const svn::Revision &start, const svn::Revision &end, const svn::Revision &peg, const QString &, bool list_files, int limit, QWidget *parent = 0); - svn::LogEntriesMapPtr getLog(const svn::Revision &start, const svn::Revision &end, const svn::Revision &peg, const QString &, bool list_files, int limit, bool follow_nodes, QWidget *parent = 0); + svn::LogEntriesMapPtr getLog(const svn::Revision &start, const svn::Revision &end, const svn::Revision &peg, const QString &, bool list_files, int limit, QWidget *parent = nullptr); + svn::LogEntriesMapPtr getLog(const svn::Revision &start, const svn::Revision &end, const svn::Revision &peg, const QString &, bool list_files, int limit, bool follow_nodes, QWidget *parent = nullptr); virtual bool getSingleLog(svn::LogEntry &, const svn::Revision &, const QString &, const svn::Revision &, QString &root); void makeBlame(const svn::Revision &start, const svn::Revision &end, SvnItem *k); - void makeBlame(const svn::Revision &start, const svn::Revision &end, const QString &, QWidget *parent = 0, const svn::Revision &peg = svn::Revision::UNDEFINED, SimpleLogCb *_acb = 0); + void makeBlame(const svn::Revision &start, const svn::Revision &end, const QString &, QWidget *parent = nullptr, const svn::Revision &peg = svn::Revision::UNDEFINED, SimpleLogCb *_acb = nullptr); void makeUpdate(const svn::Targets &targets, const svn::Revision &rev, svn::Depth depth); bool makeSwitch(const QUrl &rUrl, const QString &tPath, const svn::Revision &r, svn::Depth depth, const svn::Revision &peg, bool stickydepth, bool ignore_externals, bool allow_unversioned); bool makeSwitch(const QString &path, const QUrl &what); bool makeRelocate(const QUrl &fUrl, const QUrl &tUrl, const QString &path, bool recursive, bool ignore_externals); bool makeCheckout(const QString &, const QString &, const svn::Revision &, const svn::Revision &, svn::Depth, bool isExport, bool openit, bool ignore_externals, bool overwrite, bool ignoreKeywords, QWidget *p); void makeInfo(const SvnItemList &lst, const svn::Revision &, const svn::Revision &, bool recursive = true); void makeInfo(const QStringList &lst, const svn::Revision &, const svn::Revision &, bool recursive = true); bool makeCommit(const svn::Targets &); void CheckoutExport(const QUrl &what, bool _exp, bool urlisTarget = false); QString getInfo(const SvnItemList &lst, const svn::Revision &rev, const svn::Revision &peg, bool recursive, bool all = true); QString getInfo(const QString &_what, const svn::Revision &rev, const svn::Revision &peg, bool recursive, bool all = true); QString getInfo(const svn::InfoEntries &entries, const QString &what, bool all); QString makeMkdir(const QString &); bool makeMkdir(const svn::Targets &which, const QString &logMessage); bool isLocalWorkingCopy(const QString &path, QUrl &repoUrl); bool createUpdateCache(const QString &what); bool checkUpdateCache(const QString &path)const; bool isUpdated(const QString &path)const; bool getUpdated(const QString &path, svn::StatusPtr &d)const; void clearUpdateCache(); void removeFromUpdateCache(const QStringList &what, bool exact_only); void stopCheckModifiedThread(); void stopCheckUpdateThread(); void startFillCache(const QString &path, bool startup = false); void stopMain(); void killallThreads(); bool checkUpdatesRunning(); void getaddedItems(const QString &path, svn::StatusEntries &target); bool makeCopy(const QString &, const QString &, const svn::Revision &rev); bool makeCopy(const QList &, const QString &, const svn::Revision &rev); bool makeMove(const QString &, const QString &); bool makeMove(const QList &, const QString &); virtual bool makeCleanup(const QString &); bool get(const QString &what, const QString &to, const svn::Revision &rev, const svn::Revision &peg, QWidget *p); bool singleInfo(const QString &what, const svn::Revision &rev, svn::InfoEntry &target, const svn::Revision &_peg = svn::Revision::UNDEFINED); bool hasMergeInfo(const QString &originpath); void setContextData(const QString &, const QString &); void clearContextData(); QString getContextData(const QString &)const; bool threadRunning(ThreadType which) const; bool doNetworking(); virtual void doCommit(const SvnItemList &); virtual void editProperties(SvnItem *k, const svn::Revision &rev); protected: QScopedPointer m_Data; void showInfo(const QStringList &infoList); void CheckoutExportCurrent(bool _exp); void makeAdd(bool rec); CheckModifiedThread *m_CThread, *m_UThread; FillCacheThread *m_FCThread; void makeDiffinternal(const QString &, const svn::Revision &, const QString &, const svn::Revision &, QWidget *, const svn::Revision &peg = svn::Revision::UNDEFINED); void makeDiffExternal(const QString &p1, const svn::Revision &start, const QString &p2, const svn::Revision &end, const svn::Revision &_peg, bool isDir, QWidget *p, bool rec = true); public Q_SLOTS: virtual void dispDiff(const QByteArray &); virtual void slotNotifyMessage(const QString &); virtual void slotUpdateHeadRec(); virtual void slotUpdateTo(); virtual void slotAdd(); virtual void slotAddRec(); virtual void slotCheckoutCurrent(); virtual void slotExportCurrent(); virtual void slotCheckout(); virtual void slotExport(); virtual void slotRevert(); virtual void slotRevertItems(const QStringList &); virtual void slotSwitch(); virtual void slotResolved(const QString &); virtual void slotResolve(const QString &); virtual void makeDiff(const QString &, const svn::Revision &, const svn::Revision &, const svn::Revision &_peg, bool isDir); virtual void makeDiff(const QString &, const svn::Revision &, const QString &, const svn::Revision &); virtual void makeDiff(const QString &, const svn::Revision &, const QString &, const svn::Revision &, const svn::Revision &, bool, QWidget *p); virtual void makeDiff(const QString &, const svn::Revision &, const QString &, const svn::Revision &, QWidget *); virtual void makeNorecDiff(const QString &, const svn::Revision &, const QString &, const svn::Revision &, QWidget *); virtual void slotImport(const QString &, const QUrl &, const QString &, svn::Depth, bool noIgnore, bool noUnknown); virtual void slotMergeWcRevisions(const QString &, const svn::Revision &, const svn::Revision &, bool, bool, bool, bool, bool); virtual void slotMerge(const QString &, const QString &, const QString &, const svn::Revision &, const svn::Revision &, const svn::Revision &, bool, bool, bool, bool, bool, bool, bool); virtual void slotMergeExternal(const QString &src1, const QString &src2, const QString &target, const svn::Revision &rev1, const svn::Revision &rev2, const svn::Revision &_peg, bool); virtual void slotExtraLogMsg(const QString &); virtual void slotMakeCat(const svn::Revision &start, const QString &what, const QString &disp, const svn::Revision &peg, QWidget *dlgparent); virtual void slotCancel(bool); virtual void stopFillCache(); Q_SIGNALS: void clientException(const QString &); void sendNotify(const QString &); void reinitItem(SvnItem *); void sigRefreshAll(); void sigThreadsChanged(); void sigRefreshCurrent(SvnItem *); void sigRefreshIcons(); void sigExtraLogMsg(const QString &); void sigGotourl(const QUrl &); void sigCacheStatus(qlonglong, qlonglong); void sigCacheDataChanged(); void sigItemsReverted(const QStringList &); void sigExtraStatusMessage(const QString &); protected Q_SLOTS: virtual void checkModifiedThread(); virtual void checkUpdateThread(); virtual void slotProcessDataRead(const QByteArray &, WatchedProcess *); }; #endif diff --git a/src/svnfrontend/svnlogdlgimp.cpp b/src/svnfrontend/svnlogdlgimp.cpp index d2d78dd3..6d09c654 100644 --- a/src/svnfrontend/svnlogdlgimp.cpp +++ b/src/svnfrontend/svnlogdlgimp.cpp @@ -1,560 +1,560 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "svnlogdlgimp.h" #include "settings/kdesvnsettings.h" #include "svnactions.h" #include "svnfrontend/fronthelpers/revisionbuttonimpl.h" #include "svnfrontend/models/logitemmodel.h" #include "svnfrontend/models/logmodelhelper.h" #include "helpers/windowgeometryhelper.h" #include #include #include #include #include #include #include #include const QLatin1String groupName("log_dialog_size"); SvnLogDlgImp::SvnLogDlgImp(SvnActions *ac, bool modal, QWidget *parent) : QDialog(parent) { setupUi(this); setModal(modal); m_pbClose->setDefault(true); m_pbClose->setShortcut(Qt::CTRL | Qt::Key_Return); KStandardGuiItem::assign(m_pbClose, KStandardGuiItem::Close); KStandardGuiItem::assign(m_pbHelp, KStandardGuiItem::Help); m_DispPrevButton->setIcon(QIcon::fromTheme(QStringLiteral("kdesvndiff"))); m_DispSpecDiff->setIcon(QIcon::fromTheme(QStringLiteral("kdesvndiff"))); buttonBlame->setIcon(QIcon::fromTheme(QStringLiteral("kdesvnblame"))); - m_SortModel = 0; - m_CurrentModel = 0; + m_SortModel = nullptr; + m_CurrentModel = nullptr; m_ControlKeyDown = false; if (Kdesvnsettings::self()->log_always_list_changed_files()) { buttonListFiles->hide(); } else { m_ChangedList->hide(); } m_Actions = ac; KConfigGroup cs(Kdesvnsettings::self()->config(), groupName); QByteArray t1 = cs.readEntry("logsplitter", QByteArray()); if (!t1.isEmpty()) { m_centralSplitter->restoreState(t1); } t1 = cs.readEntry("right_logsplitter", QByteArray()); if (!t1.isEmpty()) { if (cs.readEntry("laststate", false) == m_ChangedList->isHidden()) { m_rightSplitter->restoreState(t1); } } } SvnLogDlgImp::~SvnLogDlgImp() { KConfigGroup cs(Kdesvnsettings::self()->config(), groupName); cs.writeEntry("right_logsplitter", m_rightSplitter->saveState()); cs.writeEntry("logsplitter", m_centralSplitter->saveState()); cs.writeEntry("laststate", m_ChangedList->isHidden()); delete m_SortModel; } void SvnLogDlgImp::dispLog(const svn::LogEntriesMapPtr &log, const QString &what, const QString &root, const svn::Revision &peg, const QString &pegUrl) { m_peg = peg; m_PegUrl = pegUrl; m_startRevButton->setNoWorking(m_PegUrl.isUrl()); m_endRevButton->setNoWorking(m_PegUrl.isUrl()); if (!m_PegUrl.isUrl() || Kdesvnsettings::remote_special_properties()) { QString s = m_Actions->searchProperty(_bugurl, QStringLiteral("bugtraq:url"), pegUrl, peg, true); if (!s.isEmpty()) { QString reg; s = m_Actions->searchProperty(reg, QStringLiteral("bugtraq:logregex"), pegUrl, peg, true); if (!s.isNull() && !reg.isEmpty()) { const QVector s1 = reg.splitRef(QLatin1Char('\n')); if (!s1.isEmpty()) { _r1.setPattern(s1.at(0).toString()); if (s1.size() > 1) { _r2.setPattern(s1.at(1).toString()); } } } } } _base = root; m_Entries = log; if (!what.isEmpty()) { setWindowTitle(i18nc("@title:window", "SVN Log of %1", what)); } else { setWindowTitle(i18nc("@title:window", "SVN Log")); } _name = what; if (!_name.startsWith(QLatin1Char('/'))) { _name = QLatin1Char('/') + _name; } dispLog(log); } void SvnLogDlgImp::dispLog(const svn::LogEntriesMapPtr &_log) { if (!_log) { return; } bool must_init = false; if (!m_SortModel) { m_SortModel = new SvnLogSortModel(m_LogTreeView); m_CurrentModel = new SvnLogModel(_log, _name, m_SortModel); m_SortModel->setSourceModel(m_CurrentModel); must_init = true; } else { m_CurrentModel->setLogData(_log, _name); } if (must_init) { m_LogTreeView->setModel(m_SortModel); m_LogTreeView->sortByColumn(SvnLogModel::Revision, Qt::DescendingOrder); connect(m_LogTreeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection))); m_LogTreeView->resizeColumnToContents(SvnLogModel::Revision); m_LogTreeView->resizeColumnToContents(SvnLogModel::Author); m_LogTreeView->resizeColumnToContents(SvnLogModel::Date); } m_startRevButton->setRevision(m_CurrentModel->max()); m_endRevButton->setRevision(m_CurrentModel->min()); QModelIndex ind = m_CurrentModel->index(m_CurrentModel->rowCount(QModelIndex()) - 1); if (ind.isValid()) { m_LogTreeView->selectionModel()->select(m_SortModel->mapFromSource(ind), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); } m_LogTreeView->setFocus(); } QString SvnLogDlgImp::genReplace(const QString &r1match) { static QString anf(QStringLiteral("")); static QString end(QStringLiteral("")); QString res; if (_r2.pattern().length() < 1) { res = _bugurl; res.replace(QStringLiteral("%BUGID%"), _r1.cap(1)); res = anf + res + mid + r1match + end; return res; } int pos = 0; int count = 0; int oldpos; while (pos > -1) { oldpos = pos + count; pos = r1match.indexOf(_r2, pos + count); if (pos == -1) { break; } count = _r2.matchedLength(); res += r1match.midRef(oldpos, pos - oldpos); QString sub = r1match.mid(pos, count); QString _url = _bugurl; _url.replace(QStringLiteral("%BUGID%"), sub); res += anf + _url + mid + sub + end; } res += r1match.midRef(oldpos); return res; } void SvnLogDlgImp::replaceBugids(QString &msg) { if (!_r1.isValid() || _r1.pattern().length() < 1 || _bugurl.isEmpty()) { return; } int pos = 0; int count = 0; pos = _r1.indexIn(msg, pos + count); count = _r1.matchedLength(); while (pos > -1) { QString s1 = msg.mid(pos, count); QString rep = genReplace(s1); msg = msg.replace(pos, count, rep); pos = _r1.indexIn(msg, pos + rep.length()); count = _r1.matchedLength(); } } void SvnLogDlgImp::slotSelectionChanged(const QItemSelection ¤t, const QItemSelection &previous) { Q_UNUSED(previous); m_ChangedList->clear(); QModelIndexList _l = current.indexes(); if (_l.count() < 1) { m_DispPrevButton->setEnabled(false); buttonListFiles->setEnabled(false); buttonBlame->setEnabled(false); m_ChangedList->clear(); return; } QModelIndex _index = m_SortModel->mapToSource(_l[0]); m_CurrentModel->fillChangedPaths(_index, m_ChangedList); QTextDocumentFragment _m = QTextDocumentFragment::fromPlainText(m_CurrentModel->fullMessage(_index)); QString msg = _m.toHtml(); replaceBugids(msg); m_LogDisplay->setHtml(msg); m_DispPrevButton->setEnabled(_index.row() > 0); buttonBlame->setEnabled(true); } /*! \fn SvnLogDlgImp::slotDispPrevious() */ void SvnLogDlgImp::slotDispPrevious() { QModelIndex _index = selectedRow(); if (!_index.isValid() || _index.row() == 0) { m_DispPrevButton->setEnabled(false); return; } QModelIndex _it = m_CurrentModel->index(_index.row() - 1); if (!_it.isValid()) { m_DispPrevButton->setEnabled(false); return; } const SvnLogModelNodePtr k = m_CurrentModel->indexNode(_index); const SvnLogModelNodePtr p = m_CurrentModel->indexNode(_it); if (!k || !p) { m_DispPrevButton->setEnabled(false); return; } const QString s(_base + k->realName()); const QString e(_base + p->realName()); emit makeDiff(e, p->revision(), s, k->revision(), this); } /*! \fn SvnLogDlgImp::saveSize() */ void SvnLogDlgImp::saveSize() { WindowGeometryHelper::save(this, groupName); } void SvnLogDlgImp::slotRevisionSelected() { m_goButton->setFocus(); //m_DispSpecDiff->setEnabled( m_first && m_second && m_first != m_second); } void SvnLogDlgImp::slotDispSelected() { SvnLogModelNodePtr m_first = m_CurrentModel->indexNode(m_CurrentModel->index(m_CurrentModel->leftRow())); SvnLogModelNodePtr m_second = m_CurrentModel->indexNode(m_CurrentModel->index(m_CurrentModel->rightRow())); if (m_first && m_second) { emit makeDiff(_base + m_first->realName(), m_first->revision(), _base + m_second->realName(), m_second->revision(), this); } } bool SvnLogDlgImp::getSingleLog(svn::LogEntry &t, const svn::Revision &r, const QString &what, const svn::Revision &peg, QString &root) { root = _base; const svn::LogEntriesMap::const_iterator it = m_Entries->constFind(r.revnum()); if (it == m_Entries->constEnd()) { return m_Actions->getSingleLog(t, r, what, peg, root); } t = it.value(); return true; } void SvnLogDlgImp::slotGetLogs() { svn::LogEntriesMapPtr lm = m_Actions->getLog(m_startRevButton->revision(), m_endRevButton->revision(), m_peg, _base + _name, Kdesvnsettings::self()->log_always_list_changed_files(), 0, Kdesvnsettings::last_node_follow(), this); if (lm) { dispLog(lm); } } void SvnLogDlgImp::slotPrevFifty() { svn::Revision now = m_CurrentModel->min(); if (now == 1) { return; } svn::Revision begin = now.revnum() - 1; if (begin.revnum() < 1) { begin = 1; } svn::LogEntriesMapPtr lm = m_Actions->getLog(begin, (begin.revnum() > 50 ? svn::Revision::START : svn::Revision::HEAD), m_peg, _base + _name, Kdesvnsettings::self()->log_always_list_changed_files(), 50, Kdesvnsettings::last_node_follow(), this); if (lm) { dispLog(lm); } } void SvnLogDlgImp::slotBeginHead() { svn::LogEntriesMapPtr lm = m_Actions->getLog(svn::Revision::HEAD, 1, m_peg, _base + _name, Kdesvnsettings::self()->log_always_list_changed_files(), 50, Kdesvnsettings::last_node_follow(), this); if (lm) { dispLog(lm); } } void SvnLogDlgImp::slotHelpRequested() { KHelpClient::invokeHelp(QLatin1String("logdisplay-dlg"), QLatin1String("kdesvn")); } void SvnLogDlgImp::slotListEntries() { QModelIndex _index = selectedRow(); SvnLogModelNodePtr ptr = m_CurrentModel->indexNode(_index); if (!ptr) { buttonListFiles->setEnabled(false); return; } if (ptr->changedPaths().isEmpty()) { svn::LogEntriesMapPtr _log = m_Actions->getLog(ptr->revision(), ptr->revision(), ptr->revision(), _name, true, 0, Kdesvnsettings::last_node_follow()); if (!_log) { return; } if (!_log->isEmpty()) { ptr->setChangedPaths(_log->value(ptr->revision())); } } if (ptr->changedPaths().isEmpty()) { m_CurrentModel->fillChangedPaths(_index, m_ChangedList); } buttonListFiles->setEnabled(false); } void SvnLogDlgImp::keyPressEvent(QKeyEvent *e) { if (!e) { return; } if (e->text().isEmpty() && e->key() == Qt::Key_Control) { m_ControlKeyDown = true; } QDialog::keyPressEvent(e); } void SvnLogDlgImp::keyReleaseEvent(QKeyEvent *e) { if (!e) { return; } if (e->text().isEmpty() && e->key() == Qt::Key_Control) { m_ControlKeyDown = false; } QDialog::keyReleaseEvent(e); } void SvnLogDlgImp::showEvent(QShowEvent *e) { QDialog::showEvent(e); WindowGeometryHelper::restore(this, groupName); } void SvnLogDlgImp::slotBlameItem() { QModelIndex ind = selectedRow(); if (!ind.isValid()) { buttonBlame->setEnabled(false); return; } qlonglong rev = m_CurrentModel->toRevision(ind); svn::Revision start(svn::Revision::START); m_Actions->makeBlame(start, rev, _base + m_CurrentModel->realName(ind), QApplication::activeModalWidget(), rev, this); } /* it works 'cause we use single selection only */ QModelIndex SvnLogDlgImp::selectedRow(int column) { QModelIndexList _mi = m_LogTreeView->selectionModel()->selectedRows(column); if (_mi.count() < 1) { return QModelIndex(); } return m_SortModel->mapToSource(_mi[0]); } void SvnLogDlgImp::slotCustomContextMenu(const QPoint &e) { QModelIndex ind = m_LogTreeView->indexAt(e); QModelIndex bel; if (ind.isValid()) { bel = m_LogTreeView->indexBelow(ind); ind = m_SortModel->mapToSource(ind); } int row = -1; if (ind.isValid()) { row = ind.row(); } else { return; } qlonglong rev = -1; if (bel.isValid()) { bel = m_SortModel->mapToSource(bel); rev = m_CurrentModel->toRevision(bel); } QMenu popup; QAction *ac; bool unset = false; if (row != m_CurrentModel->rightRow()) { ac = popup.addAction(QIcon::fromTheme(QStringLiteral("kdesvnright")), i18n("Set version as right side of diff")); ac->setData(101); } else { unset = true; } if (row != m_CurrentModel->leftRow()) { ac = popup.addAction(QIcon::fromTheme(QStringLiteral("kdesvnleft")), i18n("Set version as left side of diff")); ac->setData(102); } else { unset = true; } if (unset) { ac = popup.addAction(i18n("Unset version for diff")); ac->setData(103); } if (rev > -1 && !m_PegUrl.isUrl()) { ac = popup.addAction(i18n("Revert this commit")); ac->setData(104); } ac = popup.exec(m_LogTreeView->viewport()->mapToGlobal(e)); if (!ac) { return; } int r = ac->data().toInt(); switch (r) { case 101: m_CurrentModel->setRightRow(row); break; case 102: m_CurrentModel->setLeftRow(row); break; case 103: if (row != m_CurrentModel->leftRow()) { m_CurrentModel->setLeftRow(-1); } if (row != m_CurrentModel->rightRow()) { m_CurrentModel->setRightRow(-1); } break; case 104: { svn::Revision previous(rev); svn::Revision current(m_CurrentModel->toRevision(ind)); QString _path = m_PegUrl.path(); m_Actions->slotMergeWcRevisions(_path, current, previous, true, true, false, false, false); } break; } m_DispSpecDiff->setEnabled(m_CurrentModel->leftRow() != -1 && m_CurrentModel->rightRow() != -1 && m_CurrentModel->leftRow() != m_CurrentModel->rightRow()); } void SvnLogDlgImp::slotChangedPathContextMenu(const QPoint &e) { QTreeWidgetItem *_item = m_ChangedList->currentItem(); if (!_item) { return; } LogChangePathItem *item = static_cast(_item); if (item->action() == 'D') { return; } QModelIndex ind = selectedRow(); if (!ind.isValid()) { return; } const qlonglong rev = m_CurrentModel->toRevision(ind); QMenu popup; const QString name = item->path(); const QString source = item->revision() > -1 ? item->source() : item->path(); QAction *ac; ac = popup.addAction(i18n("Annotate")); if (ac) { ac->setData(101); } if (item->action() != 'A' || item->revision() > -1) { ac = popup.addAction(i18n("Diff previous")); if (ac) { ac->setData(102); } } ac = popup.addAction(i18n("Cat this version")); if (ac) { ac->setData(103); } ac = popup.exec(m_ChangedList->viewport()->mapToGlobal(e)); if (!ac) { return; } int r = ac->data().toInt(); svn::Revision start(svn::Revision::START); switch (r) { case 101: { m_Actions->makeBlame(start, rev, _base + name, QApplication::activeModalWidget(), rev, this); break; } case 102: { const svn_revnum_t prev = item->revision() > 0 ? item->revision() : rev - 1; emit makeDiff(_base + source, prev, _base + name, rev, this); break; } case 103: { emit makeCat(rev, _base + source, source, rev, QApplication::activeModalWidget()); } default: break; } } void SvnLogDlgImp::slotSingleDoubleClicked(QTreeWidgetItem *_item, int) { if (!_item) { return; } const LogChangePathItem *item = static_cast(_item); const QModelIndex ind = selectedRow(); if (!ind.isValid()) { return; } svn::Revision start(svn::Revision::START); if (item->action() != 'D') { const QString name = item->path(); const qlonglong rev = m_CurrentModel->toRevision(ind); m_Actions->makeBlame(start, rev, _base + name, QApplication::activeModalWidget(), rev, this); } } diff --git a/src/svnfrontend/svnlogdlgimp.h b/src/svnfrontend/svnlogdlgimp.h index 828edaf0..af70bcd5 100644 --- a/src/svnfrontend/svnlogdlgimp.h +++ b/src/svnfrontend/svnlogdlgimp.h @@ -1,98 +1,98 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht * * ral@alwins-world.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef SVNLOGDLGIMP_H #define SVNLOGDLGIMP_H #include "ui_svnlogdlg.h" #include "simple_logcb.h" #include "svnqt/log_entry.h" #include "svnqt/client.h" #include class QDialogButtonBox; class QKeyEvent; class QTreeWidgetItem; class SvnActions; class SvnLogModel; class QSortFilterProxyModel; class QModelIndex; class SvnLogDlgImp: public QDialog, public Ui::LogDialog, public SimpleLogCb { Q_OBJECT public: - SvnLogDlgImp(SvnActions *ac, bool modal, QWidget *parent = 0); + SvnLogDlgImp(SvnActions *ac, bool modal, QWidget *parent = nullptr); virtual ~SvnLogDlgImp(); void dispLog(const svn::LogEntriesMapPtr &log, const QString &what, const QString &root, const svn::Revision &peg, const QString &pegUrl); void saveSize(); virtual bool getSingleLog(svn::LogEntry &t, const svn::Revision &r, const QString &what, const svn::Revision &peg, QString &root); signals: void makeDiff(const QString &, const svn::Revision &, const QString &, const svn::Revision &, QWidget *); void makeCat(const svn::Revision &, const QString &, const QString &, const svn::Revision &, QWidget *); protected: virtual void keyPressEvent(QKeyEvent *e); virtual void keyReleaseEvent(QKeyEvent *e); virtual void showEvent(QShowEvent *e); protected slots: void slotDispPrevious(); void slotDispSelected(); void slotRevisionSelected(); void slotPrevFifty(); void slotBeginHead(); void slotHelpRequested(); private: QString _name; QString _base; SvnActions *m_Actions; bool m_ControlKeyDown; svn::LogEntriesMapPtr m_Entries; SvnLogModel *m_CurrentModel; QSortFilterProxyModel *m_SortModel; QString _bugurl; void dispLog(const svn::LogEntriesMapPtr &); QRegExp _r1, _r2; protected slots: void slotListEntries(); void slotChangedPathContextMenu(const QPoint &); void slotSingleDoubleClicked(QTreeWidgetItem *, int); void slotGetLogs(); void slotBlameItem(); void slotSelectionChanged(const QItemSelection &, const QItemSelection &); void slotCustomContextMenu(const QPoint &); protected: /* it works 'cause we use single selection only */ QModelIndex selectedRow(int column = 0); void replaceBugids(QString &msg); QString genReplace(const QString &); svn::Revision m_peg; svn::Path m_PegUrl; }; #endif diff --git a/src/svnfrontend/svntreeview.cpp b/src/svnfrontend/svntreeview.cpp index d671e6a8..ffafe66b 100644 --- a/src/svnfrontend/svntreeview.cpp +++ b/src/svnfrontend/svntreeview.cpp @@ -1,157 +1,157 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht ral@alwins-world.de * * http://kdesvn.alwins-world.de/ * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "svntreeview.h" #include "models/svnitemmodel.h" #include "models/svnitemnode.h" #include #include #include #include #include #include #include #include #include #include SvnTreeView::SvnTreeView(QWidget *parent) : QTreeView(parent) { } SvnTreeView::~SvnTreeView() { } void SvnTreeView::startDrag(Qt::DropActions supportedActions) { // only one dragging at time static bool isDrag = false; if (isDrag) { return; } isDrag = true; const QModelIndexList indexes = selectionModel()->selectedRows(); if (!indexes.isEmpty()) { QMimeData *data = model()->mimeData(indexes); - if (data == 0) { + if (data == nullptr) { isDrag = false; return; } QDrag *drag = new QDrag(this); QPixmap pixmap; if (indexes.count() == 1) { QAbstractProxyModel *proxyModel = static_cast(model()); SvnItemModel *itemModel = static_cast(proxyModel->sourceModel()); const QModelIndex index = proxyModel->mapToSource(indexes.first()); SvnItemModelNode *item = itemModel->nodeForIndex(index); pixmap = item->getPixmap(KIconLoader::SizeMedium, false); } else { pixmap = QIcon::fromTheme(QStringLiteral("document-multiple")).pixmap(KIconLoader::SizeMedium, KIconLoader::SizeMedium); } drag->setPixmap(pixmap); drag->setMimeData(data); drag->exec(supportedActions, Qt::IgnoreAction); } isDrag = false; } void SvnTreeView::dropEvent(QDropEvent *event) { if (!event->mimeData()->hasUrls()) { return; } QAbstractProxyModel *proxyModel = static_cast(model()); const QModelIndex index = indexAt(event->pos()); const QModelIndex index2(index.isValid() ? proxyModel->mapToSource(index) : QModelIndex()); QMap metaMap; Qt::DropAction action = event->dropAction(); const QList list = KUrlMimeData::urlsFromMimeData(event->mimeData(), KUrlMimeData::PreferLocalUrls, &metaMap); bool intern = false; if (metaMap.contains(QStringLiteral("kdesvn-source"))) { SvnItemModel *itemModel = static_cast(proxyModel->sourceModel()); QMap::const_iterator it = metaMap.constFind(QStringLiteral("kdesvn-id")); if (it != metaMap.constEnd() && it.value() == itemModel->uniqueIdentifier()) { intern = true; } } Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers(); QMetaObject::invokeMethod(this, "doDrop", Q_ARG(QList, list), Q_ARG(QModelIndex, index2), Q_ARG(bool, intern), Q_ARG(Qt::DropAction, action), Q_ARG(Qt::KeyboardModifiers, modifiers) ); event->acceptProposedAction(); } void SvnTreeView::doDrop(const QList &list, const QModelIndex &parent, bool intern, Qt::DropAction action, Qt::KeyboardModifiers modifiers) { if (intern && ((modifiers & Qt::ControlModifier) == 0) && ((modifiers & Qt::ShiftModifier) == 0)) { QMenu popup; QString seq = QKeySequence(Qt::ShiftModifier).toString(); seq.chop(1); // chop superfluous '+' QAction *popupMoveAction = new QAction(i18n("&Move Here") + QLatin1Char('\t') + seq, this); popupMoveAction->setIcon(QIcon::fromTheme(QStringLiteral("go-jump"))); seq = QKeySequence(Qt::ControlModifier).toString(); seq.chop(1); QAction *popupCopyAction = new QAction(i18n("&Copy Here") + QLatin1Char('\t') + seq, this); popupCopyAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy"))); QAction *popupCancelAction = new QAction(i18n("C&ancel") + QLatin1Char('\t') + QKeySequence(Qt::Key_Escape).toString(), this); popupCancelAction->setIcon(QIcon::fromTheme(QStringLiteral("process-stop"))); popup.addAction(popupMoveAction); popup.addAction(popupCopyAction); popup.addSeparator(); popup.addAction(popupCancelAction); QAction *result = popup.exec(QCursor::pos()); if (result == popupCopyAction) { action = Qt::CopyAction; } else if (result == popupMoveAction) { action = Qt::MoveAction; } else if (result == popupCancelAction || !result) { return; } } QAbstractProxyModel *proxyModel = static_cast(model()); SvnItemModel *itemModel = static_cast(proxyModel->sourceModel()); QModelIndex _p; if (!parent.isValid() && (_p = rootIndex()).isValid()) { QAbstractProxyModel *proxyModel = static_cast(model()); _p = proxyModel->mapToSource(_p); } else { _p = parent; } itemModel->dropUrls(list, action, parent.row(), parent.column(), _p, intern); } diff --git a/src/svnfrontend/svntreeview.h b/src/svnfrontend/svntreeview.h index 746fef79..a6e1e902 100644 --- a/src/svnfrontend/svntreeview.h +++ b/src/svnfrontend/svntreeview.h @@ -1,40 +1,40 @@ /*************************************************************************** * Copyright (C) 2005-2009 by Rajko Albrecht ral@alwins-world.de * * http://kdesvn.alwins-world.de/ * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef SVNTREEVIEW_H #define SVNTREEVIEW_H #include class SvnTreeView: public QTreeView { Q_OBJECT public: - explicit SvnTreeView(QWidget *parent = 0); + explicit SvnTreeView(QWidget *parent = nullptr); virtual ~SvnTreeView(); protected: virtual void startDrag(Qt::DropActions supportedActions); virtual void dropEvent(QDropEvent *event); protected Q_SLOTS: void doDrop(const QList &, const QModelIndex &, bool, Qt::DropAction, Qt::KeyboardModifiers); }; #endif