summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Golubev <fatzer2@gmail.com>2016-05-07 13:20:21 +1000
committerMichele Calgaro <michele.calgaro@yahoo.it>2016-05-07 13:20:21 +1000
commit8cf274c35a83bf829a54cf22f0c82fdbfb333c03 (patch)
tree6b10045d63fe191bae8dcdcaa3b3a89507a9c570
parent058176316ee0b92a9d50d0c842690869af09e3de (diff)
downloadtdeutils-8cf274c35a83bf829a54cf22f0c82fdbfb333c03.tar.gz
tdeutils-8cf274c35a83bf829a54cf22f0c82fdbfb333c03.zip
Removed crappy FileListView::updateItem() method and replace it with addOrUpdateItem()
Enhanced in several ways parsing of rar-5+ output (fixes a crash and several potential issues) Spacing fixes Minor modification: replace assert with if() Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
-rw-r--r--ark/filelistview.cpp88
-rw-r--r--ark/filelistview.h14
-rw-r--r--ark/rar.cpp169
3 files changed, 121 insertions, 150 deletions
diff --git a/ark/filelistview.cpp b/ark/filelistview.cpp
index bff5329..f951a22 100644
--- a/ark/filelistview.cpp
+++ b/ark/filelistview.cpp
@@ -72,13 +72,13 @@ int FileLVI::compare( TQListViewItem * i, int column, bool ascending ) const
if ( ( this->childCount() > 0 ) && ( item->childCount() == 0 ) )
return -1;
-
+
if ( ( this->childCount() == 0 ) && ( item->childCount() > 0 ) )
return 1;
if ( column == 0 )
return TDEListViewItem::compare( i, column, ascending );
-
+
columnName colName = ( static_cast< FileListView * > ( listView() ) )->nameOfColumn( column );
switch ( colName )
{
@@ -170,6 +170,17 @@ void FileLVI::setText( int column, const TQString &text )
TQListViewItem::setText(column, text);
}
+void FileLVI::setItemData( const TQStringList &entryData )
+{
+ int i = 0;
+
+ for (TQStringList::ConstIterator it = entryData.begin(); it != entryData.end(); ++it)
+ {
+ this->setText(i, *it);
+ ++i;
+ }
+}
+
static FileLVI* folderLVI( TDEListViewItem *parent, const TQString& name )
{
FileLVI *folder = new FileLVI( parent );
@@ -383,7 +394,7 @@ FileListView::item(const TQString& filename) const
return 0;
}
-void FileListView::addItem( const TQStringList & entries )
+FileLVI *FileListView::addItem( const TQStringList & entries )
{
FileLVI *flvi, *parent = findParent( entries[0] );
if ( parent )
@@ -391,72 +402,23 @@ void FileListView::addItem( const TQStringList & entries )
else
flvi = new FileLVI( this );
-
- int i = 0;
-
- for (TQStringList::ConstIterator it = entries.begin(); it != entries.end(); ++it)
- {
- flvi->setText(i, *it);
- ++i;
- }
+ flvi->setItemData (entries);
KMimeType::Ptr mimeType = KMimeType::findByPath( entries.first(), 0, true );
flvi->setPixmap( 0, mimeType->pixmap( TDEIcon::Small ) );
+
+ return flvi;
}
-void FileListView::updateItem( const TQStringList &entries )
+FileLVI *FileListView::addOrUpdateItem( const TQStringList &entries )
{
- TQStringList ancestorList = TQStringList::split( '/', entries[0] );
-
- // Checks if the listview contains the first item in the list of ancestors
- TQListViewItem *item = firstChild();
- while ( item )
- {
- if ( item->text( 0 ) == ancestorList[0] || item->text( 0 ) == ancestorList[0].stripWhiteSpace())
- break;
- item = item->nextSibling();
- }
-
- // If the list view does not contain the item ...
- if ( !item )
- {
- kdError( 1601 ) << ancestorList[0] << " not found" << endl;
- return;
- }
-
- // We've already dealt with the first item, remove it
- ancestorList.pop_front();
-
- while ( ancestorList.count() > 0 )
- {
- TQString name = ancestorList[0];
-
- FileLVI *parent = static_cast< FileLVI*>( item );
- item = parent->firstChild();
- while ( item )
- {
- if ( item->text(0) == name )
- break;
- item = item->nextSibling();
- }
-
- if ( !item )
- {
- kdError( 1601 ) << name << " not found" << endl;
- return;
- }
-
- ancestorList.pop_front();
+ FileLVI *flvi = item ( entries[0] );
+ if (flvi) {
+ flvi->setItemData (entries);
+ return flvi;
+ } else {
+ return addItem (entries);
}
-
- int i = 0;
- for (TQStringList::ConstIterator it = entries.begin(); it != entries.end(); ++it)
- {
- item->setText(i, *it);
- ++i;
- }
-
- item->setOpen( true );
}
void FileListView::selectAll()
@@ -481,7 +443,7 @@ void FileListView::setHeaders( const ColumnList& columns )
int colnum = addColumn( pair.first );
setColumnAlignment( colnum, pair.second );
}
-
+
setResizeMode( TQListView::LastColumn );
header()->show();
diff --git a/ark/filelistview.h b/ark/filelistview.h
index d3dd616..022ab86 100644
--- a/ark/filelistview.h
+++ b/ark/filelistview.h
@@ -60,6 +60,8 @@ class FileLVI : public TDEListViewItem
int compare ( TQListViewItem * i, int col, bool ascending ) const;
virtual TQString key( int column, bool ) const;
virtual void setText( int column, const TQString &text );
+ /// Set the data for model entry all at once
+ void setItemData( const TQStringList &entryData );
private:
TDEIO::filesize_t m_fileSize;
@@ -74,7 +76,7 @@ typedef TQValueList< TQPair< TQString, TQt::AlignmentFlags > > ColumnList;
class FileListView: public TDEListView
{
Q_OBJECT
-
+
public:
FileListView( TQWidget *parent = 0, const char* name = 0 );
@@ -109,15 +111,17 @@ class FileListView: public TDEListView
/**
* Adds a file and stats to the file listing
* @param entries A stringlist of the entries for each column of the list.
+ * @return The newly added FileLVI
*/
- void addItem( const TQStringList& entries );
+ FileLVI* addItem( const TQStringList& entries );
/**
- * Updates a file or folder item already included in the listview
+ * Adds a file and stats if it doesn't exists or updates the existing one
* @param entries A stringlist of the updated entries for each column of the list.
+ * @return The newly added or the updated FileLVI
*/
- void updateItem( const TQStringList& entries );
-
+ FileLVI* addOrUpdateItem( const TQStringList& entries );
+
/**
* Returns the number of files in the archive.
*/
diff --git a/ark/rar.cpp b/ark/rar.cpp
index 103f4ce..02600d5 100644
--- a/ark/rar.cpp
+++ b/ark/rar.cpp
@@ -30,6 +30,8 @@
#include <string>
// QT includes
+#include <tqstring.h>
+#include <tqregexp.h>
#include <tqfile.h>
#include <tqdir.h>
#include <tqtextcodec.h>
@@ -39,6 +41,7 @@
#include <tdeglobal.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
+#include <kmimetype.h>
#include <kpassdlg.h>
#include <kprocess.h>
#include <kstandarddirs.h>
@@ -83,94 +86,96 @@ RarArch::RarArch( ArkWidget *_gui, const TQString & _fileName )
verifyUncompressUtilityIsAvailable( m_unarchiver_program );
setReadOnly( true );
}
-
- m_headerString = "";
}
bool RarArch::processLine( const TQCString &line )
{
- TQString unicode_line;
-
- TQTextCodec *codec = TQTextCodec::codecForLocale();
- unicode_line = codec->toUnicode( line );
-
- // Look for rar/unrar version first
- if (!m_version)
- {
- if (line.left(3) == "RAR")
- {
- bool ok_flag = false;
- short version = line.mid(4, 1).toShort(&ok_flag);
- if (ok_flag)
- {
- m_version = version;
- if (m_version < VERSION_5)
- {
- m_headerString = "-------------------------------------------------------------------------------";
- m_isFirstLine = true;
- }
- else
- {
- m_headerString = "----------- --------- -------- ----- ---------- ----- -------- ----";
- }
- setHeaders();
- return true;
- }
- }
- return false;
- }
-
- if (m_version < VERSION_5 && m_isFirstLine)
+ TQString uline = TQTextCodec::codecForLocale()->toUnicode(line);
+
+ // Look for rar/unrar version first
+ if (!m_version)
{
- m_entryFilename = TQString::fromLocal8Bit( line );
- m_entryFilename.remove( 0, 1 );
- m_isFirstLine = false;
- return true;
+ TQRegExp versionRegExp (TQString::fromLatin1 ("RAR\\s(\\d+)\\.(\\S+)\\s.*"));
+
+ if (versionRegExp.exactMatch (uline))
+ {
+ m_version = versionRegExp.capturedTexts()[1].toShort ();
+
+ if (m_version < VERSION_5) {
+ m_headerString = "-------------------------------------------------------------------------------";
+ m_isFirstLine = true;
+ } else {
+ m_headerString = "----------- --------- -------- ----- ---------- ----- -------- ----";
+ }
+ setHeaders(); //< Note: header order for version 5 is different, but keep the old one for consistency
+ return true;
+ }
+ return false;
}
- TQStringList list;
- TQStringList l2 = TQStringList::split( ' ', line );
+ TQStringList entry;
+ TQStringList parsedData = TQStringList::split(QChar(' '), uline);
- if (m_version < VERSION_5)
+ if (m_version < VERSION_5) {
+ if (m_isFirstLine)
+ {
+ m_entryFilename = uline.remove( 0, 1 );
+ m_isFirstLine = false;
+ return true;
+ }
+
+ if (parsedData.size() < 9) {
+ kdError ( 1601 ) << "Failed to parse rar<5 output string: \"" << uline << "\"" << endl;
+ }
+
+ entry << m_entryFilename; // filename
+ entry << parsedData[ 0 ]; // size
+ entry << parsedData[ 1 ]; // packed
+ entry << parsedData[ 2 ]; // ratio
+
+ TQStringList date = TQStringList::split( '-', parsedData[ 3 ] );
+ entry << ArkUtils::fixYear( date[ 2 ].latin1() ) + '-' + date[ 1 ] + '-' + date [ 0 ] + ' ' + parsedData[4]; // date
+ entry << parsedData[ 5 ]; // attributes
+ entry << parsedData[ 6 ]; // crc
+ entry << parsedData[ 7 ]; // method
+ entry << parsedData[ 8 ]; // Version
+
+ m_isFirstLine = true;
+ }
+ else
{
- list << m_entryFilename; // filename
- list << l2[ 0 ]; // size
- list << l2[ 1 ]; // packed
- list << l2[ 2 ]; // ratio
-
- TQStringList date = TQStringList::split( '-', l2[ 3 ] );
- list << ArkUtils::fixYear( date[ 2 ].latin1() ) + '-' + date[ 1 ] + '-' + date [ 0 ] + ' ' + l2[4]; // date
- list << l2[ 5 ]; // attributes
- list << l2[ 6 ]; // crc
- list << l2[ 7 ]; // method
- list << l2[ 8 ]; // Version
-
- m_isFirstLine = true;
- }
- else
- {
- m_entryFilename = line.mid(line.find(l2[7]));
- list << m_entryFilename; // filename
- list << l2[ 1 ]; // size
- list << l2[ 2 ]; // packed
- list << l2[ 3 ]; // ratio
-
- TQStringList date = TQStringList::split('-', l2[4]);
- list << l2[ 4 ] + " " + l2[ 5 ]; // date and time
- list << l2[ 0 ]; // attributes
- list << l2[ 6 ]; // crc
- }
- // send to GUI
- if ( l2[6] == "00000000" )
- {
- // folders have CRC equal to 00000000
- // RAR utilities show the folders at the end of the listing so the folders
- // have been already added to the listview at this point without specifying
- // all the columns but the name. Update the item with the missing info
- m_gui->fileList()->updateItem( list );
- }
- else
- m_gui->fileList()->addItem( list );
+ // Note: don't use parsedData for names due to they may contain trailing spaces
+ TQRegExp nameRegExp (TQString::fromLatin1 ("\\s*(\\S+\\s+){6}\\S+ (.*)"));
+
+ if (parsedData.size() >= 8 && nameRegExp.exactMatch (uline)) {
+ m_entryFilename = nameRegExp.capturedTexts()[2];
+
+ entry << m_entryFilename; // filename
+ entry << parsedData[ 1 ]; // size
+ entry << parsedData[ 2 ]; // packed
+ entry << parsedData[ 3 ]; // ratio
+
+ entry << parsedData[ 4 ] + " " + parsedData[ 5 ]; // date and time
+ entry << parsedData[ 0 ]; // attributes
+ entry << parsedData[ 6 ]; // crc
+ } else {
+ kdError ( 1601 ) << "Failed to parse rar-5+ output string: \"" << uline << "\"" << endl;
+ return false;
+ }
+ }
+
+ // send to GUI
+ // Use addOrUpdateItem() rather than addItem() due to recent RAR version
+ // place directories in archive after their content.
+ FileLVI *item = m_gui->fileList()->addOrUpdateItem( entry );
+
+ // But archives packaged with older versions of ark may have directories
+ // entries first, so make sure they will get an appropriate icon
+ if (item && entry[5].find('d', 0, false) != -1) {
+ // check attr's for d (case insensitive to handle windows archives)
+ item->setPixmap( 0, KMimeType::mimeType( "inode/directory" )->pixmap( TDEIcon::Small ) );
+ }
+
return true;
}
@@ -216,9 +221,9 @@ void RarArch::setHeaders()
list.append( CRC_COLUMN );
if (m_version < VERSION_5)
{
- list.append( METHOD_COLUMN );
- list.append( VERSION_COLUMN );
- }
+ list.append( METHOD_COLUMN );
+ list.append( VERSION_COLUMN );
+ }
emit headers( list );
}