/****************************************************************************
**
** Copyright (C) 2004-2006 Frank Hemer <frank@hemer.org>,
** Tilo Riemer <riemer@crossvc.com>
**
**
**----------------------------------------------------------------------------
**
**----------------------------------------------------------------------------
**
** CrossVC is available under two different licenses:
**
** If CrossVC is linked against the GPLed version of Qt
** CrossVC is released under the terms of GPL also.
**
** If CrossVC is linked against a nonGPLed version of Qt
** CrossVC is released under the terms of the
** CrossVC License for non-Unix platforms (CLNU)
**
**
** CrossVC License for non-Unix platforms (CLNU):
**
** Redistribution and use in binary form, without modification,
** are permitted provided that the following conditions are met:
**
** 1. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 2. It is not permitted to distribute the binary package under a name
** different than CrossVC.
** 3. The name of the authors may not be used to endorse or promote
** products derived from this software without specific prior written
** permission.
** 4. The source code is the creative property of the authors.
** Extensions and development under the terms of the Gnu Public License
** are limited to the Unix platform. Any distribution or compilation of
** the source code against libraries licensed other than gpl requires
** the written permission of the authors.
**
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**
**
** CrossVC License for Unix platforms:
**
** 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, version 2 of the License.
** 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 version 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
*****************************************************************************/
#include "PatchDialogImpl.h"
#include <qapplication.h>
#include <qpushbutton.h>
#include <qradiobutton.h>
#include <qbuttongroup.h>
#include <qcombobox.h>
#include <qlineedit.h>
#include <qwhatsthis.h>
#include <qfiledialog.h>
#include <qmessagebox.h>
#include <qlayout.h>
#include <qtimer.h>
#include <assert.h>
#include "globals.h"
#include "pixmapcache.h"
#include "Validators.h"
// dir
PatchDialogImpl::PatchDialogImpl( QString dirName, QString shortDirName, QStringList * list,
QString moduleName, const QIconSet &whatsThisIconSet,
QWidget * parent)
: PatchDialog(parent, "PatchDialogImpl", true, LookAndFeel::g_modalF),
m_parent(parent),
m_name(FetchButton->name()),
m_dirName(dirName),
m_file(shortDirName),
m_pSelectedTagList(list),
m_topModuleName(moduleName),
m_fetchOverall(TRUE),
m_firstTagListOnEdit(FALSE),
m_pOldFirstTagPixmap(NULL),
m_lastFirstTagLen(0),
m_running(false),
m_patchFile(QString::null)
{
setCaption (tr("Create patch (dir)"));
removeRevisionSelection();
init(whatsThisIconSet);
}
// files
PatchDialogImpl::PatchDialogImpl( QString dirName, QStringList fileList, QStringList * list,
QString moduleName, const QIconSet &whatsThisIconSet,
QWidget * parent)
: PatchDialog(parent, "PatchDialogImpl", true, LookAndFeel::g_modalF),
m_parent(parent),
m_name(FetchButton->name()),
m_dirName(dirName),
m_file(fileList.join("-")),
m_pSelectedTagList(list),
m_topModuleName(moduleName),
m_fetchOverall(TRUE),
m_firstTagListOnEdit(FALSE),
m_pOldFirstTagPixmap(NULL),
m_lastFirstTagLen(0),
m_running(false),
m_patchFile(QString::null)
{
setCaption (tr("Create patch (files)"));
if (fileList.count() > 1) {
removeRevisionSelection();
} else {
assert(fileList.count());
revisionEdit->setValidator(new RevisionValidator(revisionEdit));
RevisionButton->setFocusPolicy(QWidget::TabFocus);
}
init(whatsThisIconSet);
}
void PatchDialogImpl::init(const QIconSet &whatsThisIconSet) {
m_pWhatsThis->setIconSet(whatsThisIconSet);
#ifdef Q_WS_MAC
m_pWhatsThis->setMaximumWidth(m_pWhatsThis->height() * 2);
#else
m_pWhatsThis->setMaximumWidth(m_pWhatsThis->height());
#endif
dateTimeEdit->dateEdit()->setOrder(LookAndFeel::g_dateTimeOrder);
dateTimeEdit->setDateTime(QDateTime::currentDateTime());
DetailGroup->hide();
tagEdit->setAutoCompletion(FALSE);
tagEdit->setValidator(new TagValidator(tagEdit));
connect( tagEdit, SIGNAL(textChanged(const QString &)), this, SLOT(textChangedFirstTag(const QString &)));
connect( tagEdit, SIGNAL(activated(const QString &)), this, SLOT(activatedFirstTag(const QString &)));
connect( tagEdit->lineEdit(), SIGNAL(selectionChanged()), this, SLOT(setSelectionFirstTag()));
connect( m_parent, SIGNAL(tagListFetched()), this, SLOT(tagListUpdated()));
connect( this, SIGNAL(getProjectTags()), m_parent, SLOT(updateProjectTagList()) );
connect( this, SIGNAL(getSelectedTags()), m_parent, SLOT(readCurrentTagList()));
tagListUpdated();
qApp->processEvents();
adjustSize();
}
PatchDialogImpl::~PatchDialogImpl()
{
// no need to delete child widgets, Qt does it all for us
}
void PatchDialogImpl::removeRevisionSelection() {
DetailGroupLayout->remove(RevisionButton);
delete RevisionButton;
RevisionButton = NULL;
DetailGroupLayout->remove(revisionEdit);
delete revisionEdit;
revisionEdit = NULL;
DetailGroupLayout->removeItem(revisionSpacer);
delete revisionSpacer;
revisionSpacer = NULL;
TagButton->setFocusPolicy(QWidget::TabFocus);
TagButton->setChecked(true);
setTabOrder(BrowseButton,TagButton);
}
void PatchDialogImpl::readProjectNameList() {
m_ProjectTagList.clear();
projectSettings->get(m_topModuleName,PROJECTTAGLIST,m_ProjectTagList);
}
void PatchDialogImpl::fetchClicked() {
if (m_running ^= true) {//not running
if (m_fetchOverall ^= TRUE) {//overall mode
emit getProjectTags();
} else {
emit getSelectedTags();
}
FetchButton->setName("stop action");
FetchButton->setText(tr("Stop"));
} else {
QTimer::singleShot(0,m_parent,SLOT(stopCurAction()));
FetchButton->setName(m_name);
if (m_fetchOverall ^= TRUE) {//overall mode
FetchButton->setText( tr("Fetch selected"));
} else {
FetchButton->setText( tr("Fetch all"));
}
}
}
void PatchDialogImpl::tagListUpdated() {
m_running = false;
if (!globalStopAction) {
m_firstTagListOnUpdate = TRUE;
m_firstTagListOnEdit = FALSE;
tagEdit->clear();
tagEdit->insertItem("T: HEAD");
if (m_fetchOverall) {
FetchButton->setText( tr("Fetch selected"));
readProjectNameList();
tagEdit->insertStringList(m_ProjectTagList);
} else {
FetchButton->setText( tr("Fetch all"));
tagEdit->insertStringList(*m_pSelectedTagList);
}
setPixmaps(tagEdit);
m_oldFirstTagText = tagEdit->currentText();
m_firstTagListOnUpdate = FALSE;
tagEdit->lineEdit()->selectAll();
}
}
void PatchDialogImpl::setPixmaps(QComboBox * box) {
int i;
for (i = 0; i < box->count(); ++i) {
QString txt = box->text(i);
if (txt.startsWith("T: ")) box->changeItem(findEmbeddedPixmap("TagTag30x16"),txt.mid(3),i);
else if (txt.startsWith("B: ")) box->changeItem(findEmbeddedPixmap("BranchTag30x16"),txt.mid(3),i);
}
m_oldFirstTagIdx = 0;
if (i == 0) {
box->insertItem(findEmbeddedPixmap("Tag30x16"),"",m_oldFirstTagIdx);
}
box->setCurrentItem(m_oldFirstTagIdx);//removes T: or B: for the lineEdit
}
void PatchDialogImpl::setSelectionFirstTag() {
if (m_firstTagListOnUpdate) return;
int start;
int end;
if (tagEdit->lineEdit()->getSelection(&start,&end)) {
m_lastFirstTagLen = start;
}
}
void PatchDialogImpl::activatedFirstTag(const QString & s) {
if (m_pOldFirstTagPixmap) {
tagEdit->changeItem(*m_pOldFirstTagPixmap,m_oldFirstTagText,m_oldFirstTagIdx);
m_pOldFirstTagPixmap = NULL;
}
m_oldFirstTagText = s;
m_oldFirstTagIdx = tagEdit->currentItem();
m_firstTagListOnEdit = FALSE;
tagEdit->lineEdit()->selectAll();
}
void PatchDialogImpl::textChangedFirstTag(const QString &txt) {
if (m_firstTagListOnUpdate) return;
int idx = -1;
for (int i = 0; i<tagEdit->count(); ++i) {
if (tagEdit->text(i).startsWith(txt)) {
idx = i;
break;
}
}
if (idx > -1 && (m_lastFirstTagLen < (int)txt.length()) || (tagEdit->text(idx).length() == txt.length()) ) {
m_firstTagListOnUpdate = TRUE;
int cursorPos = tagEdit->lineEdit()->cursorPosition();
tagEdit->setCurrentItem(idx);
QString current = tagEdit->currentText();
activatedFirstTag(current);
if (current.length() != txt.length()) tagEdit->lineEdit()->setSelection(txt.length(),current.length()-txt.length());
else tagEdit->lineEdit()->setCursorPosition(cursorPos);
m_firstTagListOnUpdate = FALSE;
} else if (m_oldFirstTagIdx == tagEdit->currentItem()) {
if (!m_firstTagListOnEdit) {
m_firstTagListOnEdit = TRUE;
QPixmap const * p = tagEdit->pixmap(m_oldFirstTagIdx);
if (p) {
m_pOldFirstTagPixmap = new QPixmap(*p);
} else {
m_pOldFirstTagPixmap = NULL;
}
tagEdit->changeItem(findEmbeddedPixmap("Tag30x16"),m_oldFirstTagText,m_oldFirstTagIdx);
}
}
m_lastFirstTagLen = txt.length();
}
QString PatchDialogImpl::getCvsCmd() {
if (DetailGroup->isVisible()) {
if (RevisionButton && RevisionButton->isChecked()) return "-r "+revisionEdit->text().stripWhiteSpace();
else if (TagButton->isChecked()) return "-r "+tagEdit->currentText().stripWhiteSpace();
else return "-D \""+dateTimeEdit->dateTime().toString("yyyy-MM-dd hh:mm")+"\"";
}
else return QString::null;
}
QString PatchDialogImpl::getPatchFile() {
return m_patchFile;
}
void PatchDialogImpl::browseClicked() {
QFileDialog* fd = new QFileDialog( this, "create patch", TRUE );
fd->setCaption(tr("Enter a file name for the patch file"));
fd->setMode( QFileDialog::AnyFile );
fd->setDir(m_dirName);
QString defaultName = m_file
+ "-diff-"
+ QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss")
+ ".patch";
fd->setSelection(defaultName);
bool bAgain = true;
while (bAgain) {
if ( fd->exec() == QDialog::Accepted) m_patchFile = fd->selectedFile();
else return;
QFile f(m_patchFile);
if (f.exists()) {
if (QMessageBox::warning (this, tr("Warning"),
tr("The file: ") + m_patchFile
+ tr(" already exists.") + "\n" + tr("Overwrite it?"),
tr("Yes"), tr("No")) != 0) return;
if (!f.remove()) {
QString msg = tr("Could not remove ") + m_patchFile + ".\n";
msg += tr("Maybe you don't have the needed permissions.") + "\n\n";
msg += tr("Do you want to save the patch into another file?");
if (QMessageBox::warning (this, tr("Warning"), msg, tr("Yes"), tr("No")) != 0) return;
continue;
}
}
// try to create the file as check for permissions
if (!f.open(IO_WriteOnly)) {
QString msg = tr("Could not create ") + m_patchFile + ".\n";
msg += tr("Maybe you don't have the needed permissions.") + "\n\n";
msg += tr("Do you want to save the patch into another file?");
if (QMessageBox::warning (this, tr("Warning"), msg, tr("Yes"), tr("No")) != 0) return;
} else {
f.close();
bAgain = false;
}
}
PatchFileEdit->setText(m_patchFile);
}
void PatchDialogImpl::fileNameChanged(const QString & f) {
OkButton->setDisabled(f.isEmpty());
m_patchFile = f;
}
void PatchDialogImpl::detailsToggled(bool state) {
if (!state) {
DetailGroup->hide();
} else {
DetailGroup->show();
}
qApp->processEvents();
adjustSize();
}
void PatchDialogImpl::okClicked () {
QFile f(m_patchFile);
if (!f.open(IO_WriteOnly)) {
QString msg = tr("Could not create ") + m_patchFile + ".\n";
msg += tr("Maybe you don't have the needed permissions.");
QMessageBox::warning (this, tr("Warning"), msg, tr("OK"));
PatchFileEdit->setFocus();
} else if (DetailGroup->isVisible()) {
if (RevisionButton && RevisionButton->isChecked() && revisionEdit->text().isEmpty()) ValidatorWarning::RevisionWarning(this);
else if (TagButton->isChecked() && tagEdit->currentText().isEmpty()) ValidatorWarning::TagWarning(this);
else emit accept();
} else emit accept();
}
void PatchDialogImpl::cancelClicked() {
emit reject();
}
void PatchDialogImpl::closeEvent(QCloseEvent *) {
emit reject();
}
void PatchDialogImpl::enterWhatsThisMode()
{
QWhatsThis::enterWhatsThisMode();
}
syntax highlighted by Code2HTML, v. 0.9.1