|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2007 by Marián Kyral *
|
|
|
|
* mkyral@email.cz *
|
|
|
|
* *
|
|
|
|
* 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., *
|
|
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
#include "plugin_sort.h"
|
|
|
|
#include "sortdialog.h"
|
|
|
|
|
|
|
|
#include <tdeaction.h>
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <map>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
|
|
|
|
class PluginView : public KXMLGUIClient
|
|
|
|
{
|
|
|
|
friend class KatePluginSort;
|
|
|
|
|
|
|
|
public:
|
|
|
|
Kate::MainWindow *win;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
KDE_EXPORT void* init_katesortplugin()
|
|
|
|
{
|
|
|
|
TDEGlobal::locale()->insertCatalogue("katesort");
|
|
|
|
return new KatePluginFactory;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KatePluginFactory::KatePluginFactory()
|
|
|
|
{
|
|
|
|
s_instance = new TDEInstance( "kate" );
|
|
|
|
}
|
|
|
|
|
|
|
|
KatePluginFactory::~KatePluginFactory()
|
|
|
|
{
|
|
|
|
delete s_instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQObject* KatePluginFactory::createObject( TQObject* parent, const char* name, const char*, const TQStringList & )
|
|
|
|
{
|
|
|
|
return new KatePluginSort( parent, name );
|
|
|
|
}
|
|
|
|
|
|
|
|
TDEInstance* KatePluginFactory::s_instance = 0L;
|
|
|
|
|
|
|
|
KatePluginSort::KatePluginSort( TQObject* parent, const char* name )
|
|
|
|
: Kate::Plugin ( (Kate::Application*)parent, name )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
KatePluginSort::~KatePluginSort()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void KatePluginSort::addView(Kate::MainWindow *win)
|
|
|
|
{
|
|
|
|
/// @todo doesn't this have to be deleted?
|
|
|
|
PluginView *view = new PluginView ();
|
|
|
|
|
|
|
|
(void) new TDEAction ( i18n("Sort"), 0, this,
|
|
|
|
SLOT( slotSort() ), view->actionCollection(),
|
|
|
|
"edit_insert_sort" );
|
|
|
|
|
|
|
|
view->setInstance (new TDEInstance("kate"));
|
|
|
|
view->setXMLFile("plugins/sort/plugin_sort.rc");
|
|
|
|
win->guiFactory()->addClient (view);
|
|
|
|
view->win = win;
|
|
|
|
|
|
|
|
m_views.append (view);
|
|
|
|
}
|
|
|
|
void KatePluginSort::removeView(Kate::MainWindow *win)
|
|
|
|
{
|
|
|
|
for (uint z=0; z < m_views.count(); z++)
|
|
|
|
if (m_views.at(z)->win == win)
|
|
|
|
{
|
|
|
|
PluginView *view = m_views.at(z);
|
|
|
|
m_views.remove (view);
|
|
|
|
win->guiFactory()->removeClient (view);
|
|
|
|
delete view;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KatePluginSort::slotSort()
|
|
|
|
{
|
|
|
|
Kate::View *kv = application()->activeMainWindow()->viewManager()->activeView();
|
|
|
|
|
|
|
|
if (! kv)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// display dialog part
|
|
|
|
SortDialog m_sortDialog;
|
|
|
|
|
|
|
|
// if only part of one row is selected. update By column part of dialog
|
|
|
|
if (! kv->getDoc()->selection().isEmpty())
|
|
|
|
{
|
|
|
|
if (kv->getDoc()->selStartLine() == kv->getDoc()->selEndLine() &&
|
|
|
|
kv->getDoc()->lineLength(kv->getDoc()->selStartLine()) != -1 )
|
|
|
|
{
|
|
|
|
uint sel_sc = kv->getDoc()->selStartCol() + 1;
|
|
|
|
uint sel_ec = kv->getDoc()->selEndCol() + 1;
|
|
|
|
if (! (sel_sc == 0 && (int) sel_ec == kv->getDoc()->lineLength(kv->getDoc()->selStartLine())))
|
|
|
|
{
|
|
|
|
m_sortDialog.m_checkBoxByCol->setChecked(true);
|
|
|
|
m_sortDialog.m_lineEditStartCol->setText(TQString::number(sel_sc,10));
|
|
|
|
m_sortDialog.m_lineEditEndCol->setText(TQString::number(sel_ec,10));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
kv->getDoc()->clearSelection();
|
|
|
|
}
|
|
|
|
if (m_sortDialog.exec() == TQDialog::Rejected)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (kv->getDoc()->selection().isEmpty())
|
|
|
|
kv->getDoc()->selectAll();
|
|
|
|
if (kv->getDoc()->selection().isEmpty())
|
|
|
|
return; // Nothing to sort !
|
|
|
|
|
|
|
|
uint sel_sl = kv->getDoc()->selStartLine();
|
|
|
|
uint sel_el = kv->getDoc()->selEndLine();
|
|
|
|
if (kv->getDoc()->selStartCol() > 0 && kv->getDoc()->selStartCol() == kv->getDoc()->lineLength(sel_sl))
|
|
|
|
sel_sl++ ;
|
|
|
|
if (kv->getDoc()->selEndCol() == 0 && kv->getDoc()->lineLength(sel_el) >0)
|
|
|
|
sel_el-- ;
|
|
|
|
|
|
|
|
// split string to lines
|
|
|
|
TQStringMultiMap strMLines; // alphabetical sort multimap
|
|
|
|
LongMultiMap longMLines; // numerical sort multimap
|
|
|
|
|
|
|
|
|
|
|
|
// Map filling...
|
|
|
|
TQString skey;
|
|
|
|
TQString sdata;
|
|
|
|
int ikey, non_num_ind;
|
|
|
|
TQRegExp rx("[^0-9]"); // Search regexp for not number character
|
|
|
|
for (uint i = sel_sl; i <= sel_el; i++)
|
|
|
|
{
|
|
|
|
sdata = kv->getDoc()->textLine(i);
|
|
|
|
skey = sdata;
|
|
|
|
if (m_sortDialog.m_checkBoxByCol->isChecked())
|
|
|
|
{
|
|
|
|
skey = skey.mid(m_sortDialog.m_lineEditStartCol->text().toInt() - 1,
|
|
|
|
m_sortDialog.m_lineEditEndCol->text().toInt() - m_sortDialog.m_lineEditStartCol->text().toInt());
|
|
|
|
// tqDebug("skey: %s", skey.ascii());
|
|
|
|
}
|
|
|
|
|
|
|
|
// tqDebug("\tLine: %d",i);
|
|
|
|
// tqDebug("Key: %s, Line content: %s", skey.ascii(),sdata.ascii());
|
|
|
|
if (m_sortDialog.m_radioButtonAlphaSort->isChecked())
|
|
|
|
{
|
|
|
|
if (m_sortDialog.m_checkBoxCase->isChecked())
|
|
|
|
{
|
|
|
|
// Case sensitive sort
|
|
|
|
strMLines.insert(std::pair<TQString, TQString>(skey ,sdata));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Case insensitive sort
|
|
|
|
strMLines.insert(std::pair<TQString, TQString>(skey.lower(), sdata));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Numeric sort
|
|
|
|
skey = skey.stripWhiteSpace();
|
|
|
|
if (skey.toLong() == 0)
|
|
|
|
{ // key is not number
|
|
|
|
non_num_ind = skey.find(rx,0);
|
|
|
|
if (non_num_ind != -1)
|
|
|
|
{ // beginning of key is number
|
|
|
|
// tqDebug("non_num_ind: %d",non_num_ind);
|
|
|
|
skey.truncate(non_num_ind);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
skey = "0";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// tqDebug("Key: %s",skey.ascii());
|
|
|
|
longMLines.insert(std::pair<long, TQString>(skey.toLong(), sdata));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert result back to document
|
|
|
|
// Remove selection
|
|
|
|
kv->getDoc()->removeText(sel_sl,0,sel_el,kv->getDoc()->lineLength(sel_el));
|
|
|
|
// kv->updateView(false);
|
|
|
|
|
|
|
|
TQStringMultiMap::iterator smit, smsit, emsit;
|
|
|
|
LongMultiMap::iterator lmit, slmit, elmit;
|
|
|
|
bool fasc;
|
|
|
|
uint i=sel_sl; // insert start line
|
|
|
|
bool first=true; // First line flag
|
|
|
|
TQString prevLine; // Store previous line (for unique purpose)
|
|
|
|
|
|
|
|
if (m_sortDialog.m_radioButtonAlphaSort->isChecked())
|
|
|
|
{
|
|
|
|
if (m_sortDialog.m_radioButtonAsc->isChecked())
|
|
|
|
{
|
|
|
|
// Ascendent
|
|
|
|
smsit=strMLines.begin();
|
|
|
|
emsit=strMLines.end();
|
|
|
|
fasc=true;
|
|
|
|
} //m_sortDialog.m_radioButtonAsc->isChecked()
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Descendent
|
|
|
|
smsit=strMLines.end();
|
|
|
|
smsit++;
|
|
|
|
emsit=strMLines.begin();
|
|
|
|
emsit--;
|
|
|
|
fasc=false;
|
|
|
|
} //m_sortDialog.m_radioButtonAsc->isChecked()
|
|
|
|
for( smit=smsit; smit != emsit; fasc ? ++smit : --smit )
|
|
|
|
{
|
|
|
|
sdata = smit->second;
|
|
|
|
skey = smit->first;
|
|
|
|
// tqDebug("Key: %s, Line content: %s", skey.ascii(),sdata.ascii());
|
|
|
|
|
|
|
|
if (m_sortDialog.m_checkBoxUnique->isChecked())
|
|
|
|
{
|
|
|
|
if ( prevLine.compare(sdata) != 0 || first ) //remove duplicities
|
|
|
|
{
|
|
|
|
// tqDebug("Inserting line: %d",i);
|
|
|
|
first = false;
|
|
|
|
prevLine = sdata;
|
|
|
|
kv->getDoc()->insertLine(i, sdata);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
} // m_sortDialog.m_checkBoxUnique->isChecked()
|
|
|
|
else
|
|
|
|
{
|
|
|
|
prevLine = sdata;
|
|
|
|
// tqDebug("Inserting line: %d",i);
|
|
|
|
kv->getDoc()->insertLine(i, sdata);
|
|
|
|
i++;
|
|
|
|
} // m_sortDialog.m_checkBoxUnique->isChecked()
|
|
|
|
} //for
|
|
|
|
} //m_sortDialog.m_radioButtonAlphaSort->isChecked()
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (m_sortDialog.m_radioButtonAsc->isChecked())
|
|
|
|
{
|
|
|
|
// Ascendent
|
|
|
|
slmit=longMLines.begin();
|
|
|
|
elmit=longMLines.end();
|
|
|
|
fasc=true;
|
|
|
|
} //m_sortDialog.m_radioButtonAsc->isChecked()
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Descendent
|
|
|
|
slmit=longMLines.end();
|
|
|
|
++slmit;
|
|
|
|
elmit=longMLines.begin();
|
|
|
|
--elmit;
|
|
|
|
fasc=false;
|
|
|
|
} //m_sortDialog.m_radioButtonAsc->isChecked()
|
|
|
|
for( lmit=slmit; lmit != elmit; fasc ? ++lmit : --lmit )
|
|
|
|
{
|
|
|
|
sdata = lmit->second;
|
|
|
|
ikey = lmit->first;
|
|
|
|
|
|
|
|
// tqDebug("Key: %d, Line content: %s", ikey,sdata.ascii());
|
|
|
|
if (m_sortDialog.m_checkBoxUnique->isChecked())
|
|
|
|
{
|
|
|
|
if ( prevLine.compare(sdata) != 0 || first ) //remove duplicities
|
|
|
|
{
|
|
|
|
// tqDebug("Inserting line: %d",i);
|
|
|
|
first = false;
|
|
|
|
prevLine = sdata;
|
|
|
|
kv->getDoc()->insertLine(i, sdata);
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
} // m_sortDialog.m_checkBoxUnique->isChecked()
|
|
|
|
else
|
|
|
|
{
|
|
|
|
prevLine = sdata;
|
|
|
|
// tqDebug("Inserting line: %d",i);
|
|
|
|
kv->getDoc()->insertLine(i, sdata);
|
|
|
|
i++;
|
|
|
|
} // m_sortDialog.m_checkBoxUnique->isChecked()
|
|
|
|
} //for
|
|
|
|
}
|
|
|
|
// Delete last blank line
|
|
|
|
kv->getDoc()->removeLine(i);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "plugin_sort.moc"
|
|
|
|
|