-
Notifications
You must be signed in to change notification settings - Fork 2
/
browsableObjects.py
511 lines (433 loc) · 17.7 KB
/
browsableObjects.py
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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
# -*- coding: utf-8 -*-#Falcon browsable objects
# Copyright (C) 2019 Yukio Nozawa <[email protected]>
# Copyright (C) 2019-2020 yamahubuki <[email protected]>
# Note: All comments except these top lines will be written in Japanese.
import os
import win32con
import win32file
import logging
import constants
import misc
import globalVars
class FalconBrowsableBase():
"""全ての閲覧可能オブジェクトに共通する基本クラス。"""
__slots__ = [
"attributes",
"attributesString",
"log",
"longAttributesString",
"canLnkTarget",
"canHardLinkTarget",
"canSynLinkTarget",
"list_backgroundColour",
"list_imageIndex"]
def __init__(self):
self.log = logging.getLogger("falcon.browsableObjects")
self.canLnkTarget = True
self.canHardLinkTarget = True
self.canSynLinkTarget = True
self.list_backgroundColour = None
self.list_imageIndex = -1
def GetAttributesString(self):
"""属性の文字列を設定する。"""
attrib = self.attributes
self.attributesString = ""
self.longAttributesString = ""
if attrib & win32file.FILE_ATTRIBUTE_READONLY:
self.attributesString += "R"
self.longAttributesString += _("読取専用")
else:
self.attributesString += "-"
if attrib & win32file.FILE_ATTRIBUTE_HIDDEN:
self.attributesString += "H"
if not self.longAttributesString == "":
self.longAttributesString += "・"
self.longAttributesString += _("隠し")
else:
self.attributesString += "-"
if attrib & win32file.FILE_ATTRIBUTE_SYSTEM:
self.attributesString += "S"
if not self.longAttributesString == "":
self.longAttributesString += "・"
self.longAttributesString += _("システム")
else:
self.attributesString += "-"
if attrib & win32con.FILE_ATTRIBUTE_REPARSE_POINT:
if not self.longAttributesString == "":
self.longAttributesString += "・"
self.longAttributesString += _("リパースポイント")
if self.longAttributesString == "":
self.longAttributesString = "なし"
return
def IsReparsePoint(self):
return self.attributes & win32con.FILE_ATTRIBUTE_REPARSE_POINT > 0
def __str__(self):
try:
return "<" + self.__class__.__name__ + " " + self.basename + ">"
except AttributeError:
return "<" + self.__class__.__name__ + "(unInitialized)>"
def __repr__(self):
try:
return "<" + self.__class__.__name__ + " " + self.basename + ">"
except AttributeError:
return "<" + self.__class__.__name__ + "(unInitialized)>"
def GetListTuple(self):
raise NotImplementedError
def __getitem__(self, index):
return self.GetListTuple()[index]
def __len__(self):
return len(self.GetListTuple())
def __setitem__(self, index, obj):
raise NotImplementedError
class File(FalconBrowsableBase):
"""ファイルを表す。このオブジェクトは情報を保持するだけで、指し示すファイルにアクセスすることはない。フルパスは計算可能なのだが、二重に値を生成したくはないので、あえて値を渡すようにしている。"""
__slots__ = [
"basename",
"creationDate",
"directory",
"fullpath",
"modDate",
"shortName",
"size",
"typeString",
"hIcon"]
def Initialize(
self,
directory="",
basename="",
fullpath="",
size=-1,
modDate=None,
attributes=-1,
typeString="",
creationDate=None,
shortName="",
hIcon=-1,
*,
relpath=""
):
"""
必要な情報をセットする。
継承しているクラスのうち、grepItemだけはここを通らないので注意。
互換性の為relpathを引数に取るが、使っていない。
"""
self.directory = directory
self.basename = basename
self.fullpath = os.path.join(directory, basename)
self.size = size
self.modDate = modDate.astimezone(globalVars.app.timezone)
self.creationDate = creationDate.astimezone(globalVars.app.timezone)
self.attributes = attributes
self.GetAttributesString()
self.typeString = typeString
self.shortName = shortName
self.hIcon = hIcon
if self.fullpath[0:2] == "\\\\":
self.canHardLinkTarget = False
def GetListTuple(self):
"""表示に必要なタプルを返す。"""
return (
self.basename,
misc.ConvertBytesTo(self.size, misc.UNIT_AUTO, True),
misc.PTime2string(self.modDate),
self.attributesString,
self.typeString
)
def GetNewAttributes(self, checks):
"""属性変更の時に使う。チェック状態のリストを受け取って、新しい属性値を帰す。変更の必要がなければ、-1を帰す。"""
attrib = self.attributes
# 繰り返しで回せるように、先にフラグ達をリストに入れておく
flags = [
win32file.FILE_ATTRIBUTE_READONLY,
win32file.FILE_ATTRIBUTE_HIDDEN,
win32file.FILE_ATTRIBUTE_SYSTEM,
win32file.FILE_ATTRIBUTE_ARCHIVE]
for i in range(len(flags)):
if checks[i] == constants.NOT_CHECKED: # チェックされてないのでフラグを折る
if attrib & flags[i]:
attrib -= flags[i]
elif checks[i] == constants.FULL_CHECKED: # チェック状態なのでフラグを立てる
if not attrib & flags[i]:
attrib += flags[i]
# end フラグを立てるか折るか
# end フラグの数だけ
return attrib if self.attributes != attrib else -1
# end GetNewAttributes
def GetRootDrivePath(self):
return misc.GetRootObject(self.fullpath).fullpath
def __setitem__(self, index, obj):
if index == 0:
self.basename = obj
self.fullpath = os.path.join(self.directory, self.basename)
else:
super().__setitem__(index, obj)
class Folder(File):
__slots__ = ["fileCount", "dirCount"]
def __init__(self, **args):
super().__init__(*args)
self.canHardLinkTarget = False
self.fileCount = -1
self.dirCount = -1
def GetListTuple(self):
"""表示に必要なタプルを返す。フォルダなのでサイズ不明(-1)の場合があり、この場合は <dir> にする。"""
if self.size == constants.DIR_SIZE_CALCURATING:
sizeString = "<計算中>"
elif self.size == constants.DIR_SIZE_CHECK_FAILED:
sizeString = "<取得失敗>"
elif self.size < 0:
sizeString = "<dir>"
else:
sizeString = misc.ConvertBytesTo(self.size, misc.UNIT_AUTO, True)
return (
self.basename,
sizeString,
misc.PTime2string(self.modDate),
self.attributesString,
self.typeString
)
class SearchedFile(File):
__slots__ = ["relpath"]
def Initialize(self, *args, relpath="", **kArgs):
super().Initialize(*args, **kArgs)
self.relpath = relpath
def GetListTuple(self):
"""表示に必要なタプルを返す。"""
return (
self.basename,
misc.ConvertBytesTo(self.size, misc.UNIT_AUTO, True),
self.relpath,
misc.PTime2string(self.modDate),
self.attributesString,
self.typeString
)
class SearchedFolder(Folder):
__slots__ = ["relpath"]
def Initialize(self, *args, relpath="", **kArgs,):
super().Initialize(*args, **kArgs)
self.relpath = relpath
def GetListTuple(self):
"""表示に必要なタプルを返す。フォルダなのでサイズ不明(-1)の場合があり、この場合は <dir> にする。"""
if self.size < 0:
return (
self.basename,
"<dir>",
self.relpath,
misc.PTime2string(self.modDate),
self.attributesString,
self.typeString)
else:
return (
self.basename,
misc.ConvertBytesTo(self.size, misc.UNIT_AUTO, True),
self.fullpath,
misc.PTime2string(self.modDate),
self.attributesString,
self.typeString)
class GrepItem(File):
def Initialize(self, ln, preview, fileobject, *, relpath=""):
"""
grepの結果は、ファイルの情報に加えて、行数・プレビュー・ヒット数を含む。ヒット数は、後から設定する。
ファイル名などは、与えられたファイルオブジェクトからとる。
互換性の為relpathを引数に取るが、使っていない。
"""
self.directory = fileobject.directory
self.basename = fileobject.basename
self.fullpath = fileobject.fullpath
self.size = fileobject.size
self.modDate = fileobject.modDate
self.creationDate = fileobject.creationDate
self.attributes = fileobject.attributes
self.attributesString = fileobject.attributesString
self.longAttributesString = fileobject.longAttributesString
self.shortName = fileobject.shortName
self.typeString = fileobject.typeString
self.ln = ln
self.preview = preview
self.hits = 0 # とりあえず入れておく
self.hIcon = fileobject.hIcon
if self.fullpath[0:2] == "\\\\":
self.canHardLinkTarget = False
def SetHitCount(self, h):
"""ヒット数を設定する。"""
self.hits = h
def GetListTuple(self):
"""表示に必要なタプルを返す。"""
return (
self.basename,
self.ln,
self.preview,
self.hits,
misc.ConvertBytesTo(self.size, misc.UNIT_AUTO, True),
misc.PTime2string(self.modDate),
self.attributesString,
self.typeString)
class Drive(FalconBrowsableBase):
"""ドライブを表す。"""
def Initialize(self, letter, free, total, type, name="", hIcon=-1):
"""
必要な情報をセットする
変数名はNetworkResourceと互換しているため、変更した場合は両方に反映すること!
"""
self.letter = letter
self.basename = letter
self.free = free
self.total = total
self.type = type
self.UpdateTypeString()
self.basename = name
self.fullpath = letter + ":\\"
self.hIcon = hIcon
def UpdateTypeString(self):
"""タイプの数値を文字列に変換し、self.typeString にセットする。"""
if self.type == win32file.DRIVE_CDROM:
discDrives = misc.getDiscDriveTypes()
self.typeString = discDrives[self.letter][1] + _(" ドライブ")
elif self.type == win32file.DRIVE_FIXED:
self.typeString = _("ローカル ディスク")
elif self.type == win32file.DRIVE_NO_ROOT_DIR:
self.typeString = _("ルートディレクトリなし")
elif self.type == win32file.DRIVE_RAMDISK:
self.typeString = _("RAM ディスク")
elif self.type == win32file.DRIVE_REMOVABLE:
self.typeString = _("リムーバブル ディスク")
elif self.type == win32file.DRIVE_REMOTE:
self.typeString = _("ネットワーク")
elif self.type == win32file.DRIVE_UNKNOWN:
self.typeString = _("不明")
else:
self.log.warning("Unknown drivetype found(" + self.type + ")")
self.typeString = _("不明")
def GetListTuple(self):
"""
表示に必要なタプルを返す。
変更した場合はNetworkResourceの方にも反映すること!
"""
return (
self.basename,
self.letter,
misc.ConvertBytesTo(
self.free,
misc.UNIT_AUTO,
True),
misc.ConvertBytesTo(
self.total,
misc.UNIT_AUTO,
True),
self.typeString)
def GetRootDrivePath(self):
return self.fullpath
def __setitem__(self, index, obj):
if index == 0:
self.basename = obj
else:
super().__setitem__(index, obj)
class Stream(FalconBrowsableBase):
"""NTFS 副ストリームを表す。このオブジェクトは情報を保持するだけで、指し示すファイルにアクセスすることはない。フルパスは計算可能なのだが、二重に値を生成したくはないので、あえて値を渡すようにしている。"""
def Initialize(self, file="", basename="", fullpath="", size=-1):
"""必要な情報をセットする"""
self.file = file
self.basename = basename
self.fullpath = fullpath
self.size = size
self.hIcon = -1 # ストリームにアイコンはない
def GetListTuple(self):
"""表示に必要なタプルを返す。"""
return (
self.basename,
misc.ConvertBytesTo(
self.size,
misc.UNIT_AUTO,
True))
def __setitem__(self, index, obj):
if index == 0:
self.basename = obj
self.fullpath = self.file + ":" + self.basename
else:
super().__setitem__(index, obj)
def GetRootDrivePath(self):
return misc.GetRootObject(self.fullpath).fullpath
class NetworkResource(FalconBrowsableBase):
"""ネットワーク上のディスクリソースを表す。このオブジェクトは情報を保持するだけで、指し示すリソースにアクセスすることはない。フルパスは計算可能なのだが、二重に値を生成したくはないので、あえて値を渡すようにしている。"""
def __init__(self):
super().__init__()
self.canHardLinkTarget = False
def Initialize(self, basename="", fullpath="", address="", hIcon=-1):
"""
必要な情報をセットする
ドライブリストに表示するため、変数名はDriveのものと互換
"""
self.basename = basename
self.fullpath = fullpath
self.letter = ""
self.free = -1
self.total = -1
self.type = -1
self.typeString = _("ネットワークリソース")
self.address = address
self.hIcon = hIcon
def GetListTuple(self):
"""
表示に必要なタプルを返す。
ここもDriveと同じ内容に統一
"""
return (self.basename, self.letter, "", "", self.typeString)
def GetRootDrivePath(self):
return self.basename
class PastProgressItem(FalconBrowsableBase):
"""貼り付けにおいて、渓谷/エラーになったファイルを表す。"""
def __init__(self):
super().__init__()
self.canLnkTarget = False
self.canHardLinkTarget = False
self.canSynLinkTarget = False
def Initialize(self, basename="", fullpath="", status="", details=""):
self.basename = basename
self.fullpath = fullpath
self.status = status
self.details = details
self.hIcon = 0
def setConfirmationManagerIndex(self, idx):
self.confirmationManagerIndex = idx
def getConfirmationManagerIndex(self):
return self.confirmationManagerIndex
def GetListTuple(self):
"""表示に必要なタプルを返す。"""
return (self.fullpath, self.status, self.details)
def __str__(self):
return "<past progress item>"
def __repr__(self):
return "<past progress item>"
class PastProgressHeader(PastProgressItem):
def __init__(self):
PastProgressItem.__init__(self)
self.percentage = 0
def Initialize(
self,
basename="",
fullpath="",
status="",
details="",
percentage=0):
PastProgressItem.Initialize(self, basename, fullpath, status, details)
self.percentage = percentage
def SetPercentage(self, percentage):
self.percentage = percentage
if int(percentage) == 100:
self.status = _("完了")
self.details = _("ctrl+w で閉じます")
def GetListTuple(self):
"""表示に必要なタプルを返す。"""
return (
self.fullpath, self.status, "%s(%s%%)" %
(self.details, self.percentage))
def __setitem__(self, index, obj):
if index == 0:
self.basename = obj
elif index == 1:
self.fullpath = obj
elif index == 2:
self.status = obj
elif index == 3:
self.details = obj
elif index == 4:
self.SetPercentage(obj)