Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

# Copyright (C) 2015 Chintalagiri Shashank 

# 

# This file is part of Tendril. 

# 

# This program is free software: you can redistribute it and/or modify 

# it under the terms of the GNU Affero General Public License as published by 

# the Free Software Foundation, either version 3 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 Affero General Public License for more details. 

# 

# You should have received a copy of the GNU Affero General Public License 

# along with this program.  If not, see <http://www.gnu.org/licenses/>. 

""" 

This file is part of tendril 

See the COPYING, README, and INSTALL files for more information 

""" 

 

from tendril.utils import log 

logger = log.get_logger(__name__, log.INFO) 

 

import os 

import qrcode 

import atexit 

import cPickle 

 

import render 

from tendril.utils.fsutils import TEMPDIR 

from tendril.utils.config import COMPANY_NAME 

from tendril.utils.config import COMPANY_LOGO_PATH 

from tendril.utils.config import INSTANCE_CACHE 

 

 

LABEL_TEMPLATES_ROOT = 'labels' 

 

 

class LabelBase(object): 

 

    templatefile = None 

 

    def __init__(self, code, ident, sno, branding=None, logo=None, 

                 include_qr=True, include_logo=True): 

        self._code = code 

        self._sno = sno 

        self._ident = ident 

        if branding is None: 

            self._branding = COMPANY_NAME 

        else: 

            self._branding = branding 

        if logo is None and include_logo is True: 

            self._logo = COMPANY_LOGO_PATH 

        else: 

            self._logo = logo 

        self._include_qr = include_qr 

        self._include_logo = include_logo 

        self._qr_path = None 

        if self._include_qr is True: 

            self._gen_qrcode() 

 

    @property 

    def code(self): 

        return self._code 

 

    @property 

    def sno(self): 

        return self._sno 

 

    @property 

    def ident(self): 

        # if len(self._ident) > 16: 

        #     return r"\tiny " + self._ident 

        # if len(self._ident) > 14: 

        #     return r"\scriptsize " + self._ident 

        # else: 

        return r"\footnotesize " + self._ident 

 

    @property 

    def branding(self): 

        return self._branding 

 

    @property 

    def include_logo(self): 

        return self._include_logo 

 

    @property 

    def include_qr(self): 

        return self._include_qr 

 

    @property 

    def logo(self): 

        return self._logo 

 

    @property 

    def qrcode(self): 

        return self._qr_path 

 

    def _gen_qrcode(self, wfpath=None): 

        if wfpath is None: 

            wfpath = os.path.join(TEMPDIR, 'qrcache') 

            if not os.path.exists(wfpath): 

                os.makedirs(wfpath) 

        qr = qrcode.make(self._ident + ' ' + self._sno) 

        self._qr_path = os.path.join( 

            wfpath, 'QR-' + self._ident + '-' + self._sno + '.png' 

        ) 

        qr.save(self._qr_path) 

 

    def __repr__(self): 

        return "<Label for " + self._ident + ' ' + self._sno + '>' 

 

 

class LabelCW1(LabelBase): 

    templatefile = os.path.join(LABEL_TEMPLATES_ROOT, 'CW1_template.tex') 

    lpp = 88 

 

 

class LabelCW3(LabelBase): 

    templatefile = os.path.join(LABEL_TEMPLATES_ROOT, 'CW3_template.tex') 

    lpp = 288 

 

 

class LabelP1(LabelBase): 

    templatefile = os.path.join(LABEL_TEMPLATES_ROOT, 'CW1_template.tex') 

    lpp = 88 

 

 

class LabelP2(LabelBase): 

    templatefile = os.path.join(LABEL_TEMPLATES_ROOT, 'P2_template.tex') 

    lpp = 120 

 

 

class LabelD1(LabelBase): 

    templatefile = os.path.join(LABEL_TEMPLATES_ROOT, 'CW1_template.tex') 

    lpp = 88 

 

 

class LabelCable1(LabelCW3): 

    def __init__(self, code, ident, sno, **kwargs): 

        super(LabelCable1, self).__init__(code, ident, sno) 

        self._desc = kwargs['desc'] 

 

    @property 

    def desc(self): 

        return self._desc 

 

    @property 

    def ident(self): 

        return self._ident 

 

 

class LabelBox1(LabelBase): 

    templatefile = os.path.join(LABEL_TEMPLATES_ROOT, 'BOX1_template.tex') 

    lpp = 51 

 

    def __init__(self, code, ident, sno, **kwargs): 

        super(LabelBox1, self).__init__(code, ident, sno) 

        self._desc = kwargs['desc'] 

 

    @property 

    def desc(self): 

        return self._desc 

 

    @property 

    def ident(self): 

        return self._ident 

 

 

class LabelPack1(LabelBase): 

    templatefile = os.path.join(LABEL_TEMPLATES_ROOT, 'PACK1_template.tex') 

    lpp = 20 

 

    def __init__(self, code, ident, sno, **kwargs): 

        super(LabelPack1, self).__init__(code, ident, sno) 

        self._desc = kwargs['desc'] 

 

    @property 

    def desc(self): 

        return self._desc 

 

    @property 

    def ident(self): 

        return self._ident 

 

 

class LabelBox2(LabelBase): 

    templatefile = os.path.join(LABEL_TEMPLATES_ROOT, 'BOX2_template.tex') 

    lpp = 51 

 

    def __init__(self, code, ident, sno, **kwargs): 

        super(LabelBox2, self).__init__(code, ident, sno) 

        self._mac = kwargs['mac'] 

        self._desc = kwargs['desc'] 

 

    @property 

    def desc(self): 

        return self._desc 

 

    @property 

    def mac(self): 

        return self._mac 

 

    @property 

    def ident(self): 

        return self._ident 

 

 

class LabelPack2(LabelBase): 

    templatefile = os.path.join(LABEL_TEMPLATES_ROOT, 'PACK2_template.tex') 

    lpp = 45 

 

    def __init__(self, code, ident, sno, **kwargs): 

        super(LabelPack2, self).__init__(code, ident, sno) 

        self._mac = kwargs['mac'] 

        self._desc = kwargs['desc'] 

 

    @property 

    def desc(self): 

        return self._desc 

 

    @property 

    def mac(self): 

        return self._mac 

 

    @property 

    def ident(self): 

        return self._ident 

 

 

class LabelIDT(LabelBase): 

    templatefile = os.path.join(LABEL_TEMPLATES_ROOT, 'IDT_template.tex') 

    lpp = 88 

 

    def __init__(self, code, ident, sno, **kwargs): 

        super(LabelIDT, self).__init__(code, ident, sno, 

                                       include_logo=False, include_qr=False) 

        self._qty = kwargs['qty'] 

 

    @property 

    def qty(self): 

        return self._qty 

 

    @property 

    def ident(self): 

        return self._ident 

 

 

def get_labelbase(code): 

    # TODO change this dispatch to use introspection instead 

    if code == 'CW1': 

        return LabelCW1 

    elif code == 'CW3': 

        return LabelCW3 

    elif code == 'D1': 

        return LabelD1 

    elif code == 'P1': 

        return LabelP1 

    elif code == 'P2': 

        return LabelP2 

    elif code == 'IDT': 

        return LabelIDT 

    elif code == 'LBOX1': 

        return LabelBox1 

    elif code == 'LPACK1': 

        return LabelPack1 

    elif code == 'LBOX2': 

        return LabelBox2 

    elif code == 'LPACK2': 

        return LabelPack2 

    elif code == 'LCABLE1': 

        return LabelCable1 

    else: 

        return LabelBase 

 

 

class LabelSheet(object): 

    def __init__(self, base, code): 

        self._base = base 

        self._code = code 

        self._labels = [] 

 

    @property 

    def code(self): 

        return self._code 

 

    @property 

    def base(self): 

        return self._base 

 

    @property 

    def labels(self): 

        for label in self._labels: 

            yield label 

 

    def add_label(self, label): 

        self._labels.append(label) 

 

    @property 

    def nl(self): 

        return len(self._labels) 

 

    def generate_pdf(self, targetfolder, force=True): 

        labels = [label for label in self._labels] 

        nl = len(labels) 

        sheets, remain = divmod(nl, self.base.lpp) 

        if nl == 0: 

            return None 

        if remain > self.base.lpp * 0.8 or force is True: 

            stage = {'labels': labels} 

            self._labels = [] 

            logger.info("Creating all labels for sheet : " + self._code) 

        elif sheets > 0: 

            stage = {'labels': labels[:self.base.lpp * sheets]} 

            self._labels = labels[self.base.lpp * sheets:] 

            logger.info("Holding back " + 

                        str(remain) + " labels for sheet : " + self._code) 

        else: 

            logger.info("Not generating labels for sheet : " + self._code + 

                        ' ' + str(remain)) 

            return None 

        return render.render_pdf( 

            stage, 

            self._base.templatefile, 

            os.path.join(targetfolder, 'labels-' + self.code + '.pdf') 

        ) 

 

    def clear_sno_label(self, sno): 

        if self._labels is None: 

            self._labels = [] 

        for label in self._labels: 

            if label.sno == sno: 

                self._labels.remove(label) 

 

 

class LabelMaker(object): 

    def __init__(self): 

        self._sheets = [] 

 

    def add_label(self, code, ident, sno, **kwargs): 

        # self._clear_sno_label(sno) 

        sheet = self._get_sheet(code) 

        label = sheet.base(code, ident, sno, **kwargs) 

        sheet.add_label(label) 

 

    def _get_sheet(self, code): 

        if code not in self._sheetdict.keys(): 

            self._sheets.append(LabelSheet(get_labelbase(code), code)) 

        return self._sheetdict[code] 

 

    @property 

    def _sheetdict(self): 

        return {x.code: x for x in self._sheets} 

 

    def generate_pdfs(self, targetfolder, force=False): 

        rval = [] 

        for sheet in self._sheets: 

            opath = sheet.generate_pdf(targetfolder, force) 

            if opath is not None: 

                rval.append(opath) 

        return rval 

 

    @property 

    def nl(self): 

        return sum([x.nl for x in self._sheets]) 

 

    def _clear_sno_label(self, sno): 

        for sheet in self._sheets: 

            sheet.clear_sno_label(sno) 

 

 

def get_manager(): 

    try: 

        with open(os.path.join(INSTANCE_CACHE, 'labelmaker.p'), 'rb') as f: 

            return cPickle.load(f) 

    except IOError: 

        return LabelMaker() 

 

manager = get_manager() 

 

 

def dump_manager(): 

    with open(os.path.join(INSTANCE_CACHE, 'labelmaker.p'), 'wb') as f: 

        cPickle.dump(manager, f) 

 

atexit.register(dump_manager)