/
archiveviewer.cpp
229 lines (202 loc) · 6.96 KB
/
archiveviewer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#include "archiveviewer.h"
#include "osinterface.h"
#include "mydialog.h"
#include "types.h"
#include "stylesheets.h"
#include "functions.h"
#include <QKeyEvent>
#include <QTreeView>
#include <QStandardItemModel>
#include <QPersistentModelIndex>
#include <QAbstractItemView>
#include <QBrush>
#include <QStandardItem>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
/* vrati index oznaceneho prvku, v tomto pripade je to hodnota ulozena pri vzniku, kvuli navratu */
int ArchiveViewer::getSelIdx(){
return idx;
}
/* zpracuje udalost predani focusu, vola focus() */
void ArchiveViewer::focusInEvent(QFocusEvent *) {
emit(focused());
if(model()){
if(selectedIndexes().empty()){ // na zacatku
QPersistentModelIndex sel_idx = indexAt(QPoint(0, 0));
setCurrentIndex(sel_idx);
}
}
focus();
}
/*
* vytvori obsah tohoto prvku;
* promenna idx ukazuje do vectoru items obsahujiciho jmena souboru z archivu.
* prislusne soubory povesi pod *it;
*/
void ArchiveViewer::buildTree(QTreeWidgetItem *it, unsigned int idx){
std::shared_ptr<Data> data_instance = Data::getInstance();
std::string name, prefix, tmp;
char last;
unsigned int pos;
try{
tmp = prefix = name = items.at(idx);
}catch(std::exception) { return; }
QTreeWidgetItem *item;
if(it != nullptr)
item = new QTreeWidgetItem();
else // top level
item = new QTreeWidgetItem(this);
if(name[name.size() - 1] == '/') //odstrani posledni lomitko
name = name.substr(0, name.size() - 1);
pos = name.find_last_of('/');
if(pos != std::string::npos)
name = name.substr(pos + 1, name.size()); //vyriznuti jmena souboru
item->setText(0, QString::fromStdString(name));
item->setIcon(0, base_icon);
while(1){ // prochazi soubory patrici pod tento
if(++idx >= items.size()) break;
try{
name = items.at(idx);
}catch(std::exception) { break; }
if((name.find('/') != std::string::npos) && (name.find(prefix) != 0)) break; // narazil na soubor, ktery uz nepatri pod tuto polozku - neobsahuje prefix (na zacatku)
last = name[name.size() - 1];
if(name != prefix)
name = (name.size() >= prefix.size() ) ?
name.substr(prefix.size(), name.size() - prefix.size() - 1) : "";
if(name.find('/') != std::string::npos) continue; // mezi prefixem a souborem je netrivialni cesta - tato polozka bude pripojena rekurzivne pozdeji
name.push_back(last);
if((name.find(prefix) == 0) | (tmp[tmp.size() - 1] == '/'))
buildTree(item, idx); // vola se pro syny
else{
buildTree(nullptr, idx);
break;
}
}
if(it != nullptr){
it->setIcon(0, dir_icon);
it->setFont(0, bold_font);
it->addChild(item);
it->setExpanded(false);
}
}
/* nacte jmena souboru v archivu do vectoru items, vcetne cest */
void ArchiveViewer::readArch(){
std::shared_ptr<Data> data_instance = Data::getInstance();
std::string ext = getExtension(path);
if (ext == "zip"){ // pro zip archivy
char *buf = new char[4], *fn;
int32_t *ptr_32 = (int32_t *) buf; //4B
int16_t *ptr_16 = (int16_t *) buf; //2B
int32_t socd;
int16_t fn_length, extra_length, comment_length;
int cur_off;
off_t offset = -4;
std::ifstream file(path, std::ios::in | std::ios::binary);
do{ //cte od konce a hleda znacku SOCD
file.seekg (offset, std::ios::end);
file.read(buf, 4);
offset -= 1;
}while(*ptr_32 != data_instance->socd_record);
file.seekg (12, std::ios::cur);
file.read(buf, 4);
socd = *ptr_32; // z prislusneho offsetu precte adresu SOCD
cur_off = socd + 28; // v promenne cur_off je aktualni offset v archivu
do{ //z prislusnych offsetu cte informace a jmena souboru, ktera prida do vectoru items
file.seekg (cur_off, std::ios::beg);
file.read(buf, 2);
fn_length = *ptr_16;
file.read(buf, 2);
extra_length = *ptr_16;
file.read(buf, 2);
comment_length = *ptr_16;
cur_off += 18; //preskocit nejake dalsi info
fn = new char[fn_length + 1];
file.seekg(cur_off, std::ios::beg);
file.read(fn, fn_length);
fn[fn_length] = '\0';
items.push_back(fn);
delete fn;
cur_off += fn_length + extra_length + comment_length; //do dalsiho zaznamu
file.seekg(cur_off, std::ios::beg);
file.read(buf, 4); //precte pro kontrolu
cur_off += 28;
}while(*ptr_32 != data_instance->socd_record); //do SOCD
}
}
/* vyvola prebudovani obsahu - od zacatku */
void ArchiveViewer::rebuild(int){
readArch();
clear();
buildTree(nullptr, 0);
setEditTriggers(QTreeWidget::NoEditTriggers);
setAlternatingRowColors(false);
setSortingEnabled(false);
setSelectionBehavior(QTreeWidget::SelectRows);
setHeaderHidden(true);
setColumnWidth(0, 280);
}
/* obsluhy udalosti */
void ArchiveViewer::focusOutEvent(QFocusEvent *){
unFocus();
}
void ArchiveViewer::resizeEvent(QResizeEvent *e)
{
w = e->size().width();
if(w)
emit(rebuilded());
}
void ArchiveViewer::setFocus(){ QTreeWidget::setFocus(); }
/* vrati jmeno aktualne oznaceneho souboru vcetne absolutni cesty */
std::string ArchiveViewer::getSelected(){
if(currentItem())
return path + OSInterface::dir_sep + currentItem()->text(0).toStdString() ;
else return "";
}
/* prestane prekazet, zrusen bude pozdeji */
void ArchiveViewer::die(){
setFocusPolicy(Qt::NoFocus);
setFixedSize(0, 0);
}
/* obsluha zmacknuti klavesy */
void ArchiveViewer::keyPressEvent(QKeyEvent *e){
if(e->key() == Qt::Key_Insert)
mark(!marked);
else if(e->key() == Qt::Key_Shift){
std::string msg("Selecting items is not allowed in archives");
MyDialog::MsgBox(msg);
}else if(e->key() == Qt::Key_Backspace){
emit(chlayout());
setFocus();
}else if(e->key() == Qt::Key_Return){
currentItem()->setExpanded(!currentItem()->isExpanded());
}else if(e->key() == Qt::Key_F1)
emit(chlayout());
else if(e->key() == Qt::Key_F11)
emit(refresh());
else // zpracuj normalne
QTreeWidget::keyPressEvent(e);
}
/* zmena stylu, priznak is_focused, vyvolava focusInEvent */
void ArchiveViewer::focus(){
is_focused = true;
setStyleSheet(focused_list_style);
}
/* pri oznaceni jako cil operace */
void ArchiveViewer::mark(bool m){
if(m){ //oznacit
marked = true;
setStyleSheet(marked_list_style);
}else{ //odznacit
marked = false;
setStyleSheet(focused_list_style);
}
}
/* kvuli zmene stylu, vyvolava se z mainwindow */
void ArchiveViewer::unFocus(){
is_focused = false;
if(!marked){
setStyleSheet(unfocused_list_style);
}else mark(true);
}