diff options
Diffstat (limited to 'BrickBrowser.py')
-rw-r--r-- | BrickBrowser.py | 657 |
1 files changed, 657 insertions, 0 deletions
diff --git a/BrickBrowser.py b/BrickBrowser.py new file mode 100644 index 0000000..4d74b87 --- /dev/null +++ b/BrickBrowser.py @@ -0,0 +1,657 @@ +import gtk +import pygtk +import random + +class BrickBrowser(gtk.DrawingArea): + + def __init__(self, wid, hei, platform, mp): + + self.main = mp + self.platform = platform + self.width, self.height = wid, hei + + self.init_data() + self.init_graphics() + gtk.DrawingArea.__init__(self) + + self.set_size_request(self.width, self.height) + + self.connect("expose_event", self.expose_event) + self.connect("configure_event", self.configure_event) + self.connect("leave_notify_event", self.leave_notify_event) + self.connect("motion_notify_event", self.motion_notify_event) + self.connect("button_press_event", self.button_press_event) + self.connect("button_release_event", self.button_release_event) + + self.set_events(gtk.gdk.EXPOSURE_MASK + | gtk.gdk.LEAVE_NOTIFY_MASK + | gtk.gdk.BUTTON_PRESS_MASK + | gtk.gdk.BUTTON_RELEASE_MASK + | gtk.gdk.POINTER_MOTION_MASK + | gtk.gdk.POINTER_MOTION_HINT_MASK) + + def init_data(self): + self.flag = 0 # 0 off 1 on + self.fix_button = 0 + self.brick_highlight = -1 + self.drag_brick = -1 + self.select_brick = -1 + self.drag_state = 0 + self.list = [] + self.listf = [] + self.list_p = 0 + self.page_cnt = [0 for i in range(1000)] + + self.all_brick_list = [] + self.active_brick_list = [] + + self.button_highlight = -1 + self.btns = ["Back","Stop","Prev","Next","Refresh","Load"] + + self.bx1 = [0 for i in range(self.main.score.tesize)] + self.bx2 = [0 for i in range(self.main.score.tesize)] + self.by = [0 for i in range(self.main.score.tesize)] + + self.no_update = False + self.update_pending = 0 + self.ready = 0 + + self.loadmode = False + + #self.create_all_list() + #self.lucky_pick() + #self.load_temp_list() + + def init_graphics(self): + self.cx = (int)(0.09 * self.width) + self.cy = 10 + self.btn_h = 42 + + self.gridw = self.main.bricksarea.gridw + self.gridh = self.main.bricksarea.gridh + self.ngrid_v = self.main.bricksarea.ngrid_v + self.ngrid_h = self.main.bricksarea.ngrid_h + + self.ahei = self.main.bricksarea.chei * 4 + self.thei = self.ahei + 4*3 + 2*2 + self.height = self.cy * 2 + self.thei + + def configure_event(self, widget, event): + x, y, width, height = widget.get_allocation() + self.pixmap = gtk.gdk.Pixmap(widget.window, width, height) + return True + + def leave_notify_event(self, widget, event): + return + + def button_press_event(self, widget, event): + self.fix_button = self.fix_button + 1 + if self.fix_button != 1: + return + if event.button == 1: + t = self.is_on_brick(event.x, event.y) +# print "Back 0 %d" % t + if t != -1: + if self.drag_state == 1 and self.loadmode: + if self.drag_brick == t: + self.drag_state = 2 + else: + self.draw_1_score(self.drag_brick, t) + self.drag_brick = t + self.filename_label.set_text(self.main.score.temp_bricks[t].filename) + self.author_label.set_text(self.main.score.temp_bricks[t].author) + if self.main.score.temp_bricks[t].filename.endswith("mps"): + name = "Composition" + elif self.main.score.temp_bricks[t].brick_type == 2: + name = "Rhythm Brick" + else: + name = "Melody Brick" + self.type_label.set_text(name) + self.scale_label.set_text(self.main.score.scale_list[self.main.score.temp_bricks[t].scale_mode]) + self.title_label.set_text(self.main.score.temp_bricks[t].title) + self.desc_label.set_text(self.main.score.temp_bricks[t].description) + self.note_label.set_text(self.main.score.temp_bricks[t].note) + else: + self.drag_brick = t + self.drag_state = 1 + else: + t = self.is_on_button(event.x, event.y) + if t != 1 and t != 5 and self.drag_state == 1: + self.drag_state = 0 + self.draw_1_score(self.drag_brick, -1) + +# print "Back 1 %d" % t + if t == 0: # back + self.main.browser_layout.remove(self.main.bricksarea) + if self.platform != "sugar-xo": + self.main.window.remove(self.main.browser_layout) + self.main.layout.put(self.main.bricksarea, 0, self.main.toolbararea_height + self.main.canvas_height) + if self.platform == "sugar-xo": + self.main.window.set_canvas(self.main.layout) + else: + self.main.window.add(self.main.layout) + self.main.window.show_all() + self.fix_button = 0 + self.flag = 0 + elif t == 1: # stop + self.main.score.stop_music(self.main.csound) + elif t == 2: # prev + if self.list_p > 0: + self.list_p = self.list_p - 1 + self.load_temp_list_1page() + self.draw_scores() + elif t == 3: # next + if self.page_cnt[self.list_p] < len(self.list): + self.list_p = self.list_p + 1 +# self.list_p = self.list_p + self.main.score.tesize + self.load_temp_list_1page() + self.draw_scores() + elif t == 4: # refresh + self.update_all_list() + elif t == 5: # load + if self.drag_state == 1: + self.main.browser_layout.remove(self.main.bricksarea) + if self.platform != "sugar-xo": + self.main.window.remove(self.main.browser_layout) + self.main.layout.put(self.main.bricksarea, 0, self.main.toolbararea_height + self.main.canvas_height) + if self.platform == "sugar-xo": + self.main.window.set_canvas(self.main.layout) + else: + self.main.window.add(self.main.layout) + self.main.window.show_all() + self.fix_button = 0 + self.flag = 0 + self.drag_state = 0 + self.main.canvas.canvas_load_score(self.main.score.temp_bricks[self.drag_brick].filename) + return + + def button_release_event(self, widget, event): + self.fix_button = 0 + if self.drag_state == 2 and self.loadmode: + t = self.is_on_brick(event.x, event.y) + if self.drag_brick == t: + self.main.score.temp_bricks[t].play_music() + self.drag_state = 1 + else: + self.draw_1_score(self.drag_brick, t) + self.brick_highlight = t + self.drag_state = 0 + elif self.drag_state == 1: + t = self.is_on_brick(event.x, event.y) + if not self.loadmode: + if self.drag_brick == t: + self.main.score.temp_bricks[t].play_music() + else: + self.draw_1_score(self.drag_brick, t) + self.brick_highlight = t + self.drag_state = 0 # drag to + if not self.loadmode: + bricka = self.main.bricksarea + score = self.main.score + t = bricka.is_on_brickarea(event.x, event.y - self.main.canvas_height) + if t: + grp = -1 + brick = score.temp_bricks[self.drag_brick] + if brick.author == self.main.username: + if brick.brick_type == 0: + grp = 1 + elif brick.brick_type == 2: + grp = 2 + else: + if brick.brick_type == 0: + grp = 4 + elif brick.brick_type == 2: + grp = 5 + if grp != -1 and bricka.add_brick(grp, brick): + if grp !=bricka.active_group: + bricka.change_active_group(grp) + else: + bricka.bricks_cnt = bricka.bricks_cnt + 1 + bricka.draw_scores() + self.active_brick_list.append(brick.filename) + self.draw_1_score(-1, self.drag_brick) + + def motion_notify_event(self, widget, event): + if event.is_hint: + x, y, state = event.window.get_pointer() + else: + x, y = event.x, event.y + state = event.state + t = self.is_on_brick(event.x, event.y) + if self.drag_state == 0 and t != self.brick_highlight and (self.brick_highlight != -1 or t != -1): + if t == -1: + self.filename_label.set_text("") + self.author_label.set_text("") + self.type_label.set_text("") + self.scale_label.set_text("") + self.title_label.set_text("") + self.desc_label.set_text("") + self.note_label.set_text("") + else: + self.filename_label.set_text(self.main.score.temp_bricks[t].filename) + self.author_label.set_text(self.main.score.temp_bricks[t].author) + if self.main.score.temp_bricks[t].filename.endswith("mps"): + name = "Composition" + elif self.main.score.temp_bricks[t].brick_type == 2: + name = "Rhythm Brick" + else: + name = "Melody Brick" + self.type_label.set_text(name) + self.scale_label.set_text(self.main.score.scale_list[self.main.score.temp_bricks[t].scale_mode]) + self.title_label.set_text(self.main.score.temp_bricks[t].title) + self.desc_label.set_text(self.main.score.temp_bricks[t].description) + self.note_label.set_text(self.main.score.temp_bricks[t].note) + self.draw_1_score(self.brick_highlight, t) + self.brick_highlight = t + t = self.is_on_button(event.x, event.y) + if self.drag_state == 0 and t != self.button_highlight: + self.button_highlight = t + self.draw_buttons() + + def expose_event(self, widget, event): + print "expose_event" + self.widget = widget + self.ready = 1 + cr = self.pixmap.cairo_create() + + # set a clip region for the expose event + x , y, width, height = event.area + cr.rectangle(x, y, width, height) + cr.clip() + + self.draw(cr) + # draw_drawable? + if self.update_pending == 1: + if self.main.type_box.get_active_text() == "Compositions": + self.draw_buttons() + self.draw_scores() + self.update_pending = 0 + widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, x, y, x, y, width, height) + return False + + def draw_curvy_rectangle(self, cr, x0, y0, x1, y1, r, highlight): + if highlight == 0: + cr.set_source_rgb(0.80,0.80,0.80) + else: + cr.set_source_rgb(0.92,0.92,0.92) + cr.move_to(x0, y0 + r) + cr.curve_to(x0, y0, x0, y0, x0+r, y0) + cr.line_to(x1-r, y0) + cr.curve_to(x1, y0, x1, y0, x1, y0+r) + cr.line_to(x1, y1-r) + cr.curve_to(x1, y1, x1, y1, x1-r, y1) + cr.line_to(x0+r, y1) + cr.curve_to(x0, y1, x0, y1, x0, y1-r) + cr.close_path() + cr.fill_preserve() + cr.set_line_width(1) + cr.set_source_rgb(0.98, 0.98, 0.98) + cr.stroke() + + def is_on_brick(self, x, y): + if y < self.cy - 2 or y > self.cy + self.ahei + 12: + return -1 + if x < self.cx or x > self.width-20: + return -1 + bricka = self.main.bricksarea + for i in range(self.main.score.temp_bricks_cnt): + if self.list_p == 0 and i >= self.page_cnt[self.list_p]: + return -1 + elif self.list_p > 0 and i >= (self.page_cnt[self.list_p] - self.page_cnt[self.list_p - 1]): + return -1 +# print "%d %d %d %d %d" % (x, y, self.bx1[i], self.bx2[i], self.by[i]) + if y >= self.by[i] and y < (self.by[i] + bricka.chei) and x >= self.bx1[i] and x < self.bx2[i]: + return i + return -1 + + def draw_1_score(self, t1, t2): + cr = self.pixmap.cairo_create() + widget = self.widget + bricka = self.main.bricksarea + ty = bricka.cy + if t1 != -1: + bricka.cy = self.by[t1] + bricka.draw_mini_score(cr, self.bx1[t1]-self.cx, self.main.score.temp_bricks[t1], self.listf[t1+self.list_p]) + if t2 != -1: + bricka.cy = self.by[t2] + bricka.draw_mini_score(cr, self.bx1[t2]-self.cx, self.main.score.temp_bricks[t2], 1) + bricka.cy = ty + widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx, 0, self.cx, 0, self.width, self.height) + + def is_on_button(self, x, y): + if x < 12 or x >= self.cx - 12: + return -1 + for i in range(len(self.btns)): + if i == len(self.btns)-1 and self.main.type_box.get_active_text() != "Compositions": + continue; + if y >= self.cy + i*self.btn_h and y < self.cy + i*self.btn_h + self.btn_h - 8: + return i + return -1 + + def draw_scores(self): + cr = self.pixmap.cairo_create() + widget = self.widget + score = self.main.score + bricka = self.main.bricksarea + self.draw_curvy_rectangle(cr, self.cx-2, self.cy-5, self.width-20+2, self.cy + self.ahei+16, 8, 0) + + x = 5 + row = 0 + ty = bricka.cy + bricka.cy = self.cy + 2 + if self.list_p == 0: + self.page_cnt[self.list_p] = score.temp_bricks_cnt + else: + self.page_cnt[self.list_p] = self.page_cnt[self.list_p-1] + score.temp_bricks_cnt + for i in range(score.temp_bricks_cnt): + brick = score.temp_bricks[i] + if x + brick.width * self.gridw > self.width-20-self.cx: + row = row + 1 + bricka.cy = bricka.cy + bricka.chei + 4 + x = 5 + if row >= 4: + if self.list_p == 0: + self.page_cnt[self.list_p] = i + 1 + else: + self.page_cnt[self.list_p] = i + 1 + self.page_cnt[self.list_p - 1] + break + if self.list_p == 0: + bricka.draw_mini_score(cr, x, brick, self.listf[i]) + else: + bricka.draw_mini_score(cr, x, brick, self.listf[i+self.page_cnt[self.list_p-1]]) + self.bx1[i] = self.cx + x + self.bx2[i] = self.cx + x + brick.width * self.gridw + self.by[i] = bricka.cy + x = x + brick.width * self.gridw + bricka.bdiv + 2 + bricka.cy = ty + widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, self.cx, 0, self.cx, 0, self.width, self.height) + + def draw(self, cr): + cr.set_source_rgb(0.84, 0.84, 1) + cr.rectangle(0, 0, self.width, self.height) + cr.fill() + + self.draw_buttons() + self.draw_scores() + + def draw_buttons(self): + cr = self.pixmap.cairo_create() + + cr.set_source_rgb(0.84, 0.84, 1) + cr.rectangle(0, 0, self.cx, self.height) + cr.fill() + + widget = self.widget + cr.set_font_size(18) + for i in range(len(self.btns)): + if i == len(self.btns)-1 and self.main.type_box.get_active_text() != "Compositions": + continue; + (x0, y0) = (12, self.cy + i * self.btn_h) + (x1, y1) = (self.cx-12, self.cy + i * self.btn_h + self.btn_h - 8) + self.draw_curvy_rectangle(cr, x0, y0, x1, y1, 4, (self.button_highlight == i)) + xb, yb, wid, hei = cr.text_extents(self.btns[i])[:4] + cr.set_source_rgb(0.4, 0.4, 0.4) + cr.move_to( (x0+x1)/2 - wid/2 - xb, (y0+y1)/2 - hei/2 - yb) + cr.show_text(self.btns[i]) + widget.window.draw_drawable(widget.get_style().fg_gc[gtk.STATE_NORMAL], self.pixmap, 0, 0, 0, 0, self.cx-3, self.height) + + def get_file_info(self, filename): + try: + n = filename.split("_") + l = len(n) + if filename.endswith("mps"): + type = -1 + else: + type = (int)(n[l-3]) + scale = (int)(n[l-2]) + if l == 4: + author = n[0] + else: + author = "" + for i in range(l-3): + author = author + n[i] + if i != l-4: + author = author + "_" + except: + return ["invalid_filename", 0, 0] + else: + return [author, type, scale] + + def update_author_list(self): + score = self.main.score + size1 = len(score.local_brick_list) + size2 = len(score.srv_brick_list) + self.main.model1.append([self.main.username]) + for i in range(size1): + [author, type, scale] = self.get_file_info(score.local_brick_list[i]) + if author == "invalid_filename": + continue; + flag = 0 + for j in range(len(self.main.model1)): + if self.main.model1[j][0] == author: + flag = 1 + break + if flag == 0: + self.main.model1.append([author]) + for i in range(size2): + [author, type, scale] = self.get_file_info(score.srv_brick_list[i]) + if author == "invalid_filename": + continue; + flag = 0 + for j in range(len(self.main.model1)): + if self.main.model1[j][0] == author: + flag = 1 + break + if flag == 0: + self.main.model1.append([author]) + + def combo_changed(self, widget, entry = None): + self.load_temp_list() + self.brick_highlight = -1 + self.drag_brick = -1 + self.drag_state = 0 + self.loadmode = (self.main.type_box.get_active_text() == "Compositions") +# if not self.loadmode: +# self.drag_state = 0 + if self.ready == 0: + self.update_pending = 1 + return + self.draw_buttons() + self.draw_scores() + + def filter(self, filename): + [author, type, scale] = self.get_file_info(filename) + if author == "invalid_filename": + return False + + af = self.main.author_box.get_active_text() + if af != "All Authors": + if author != af: + return False + + at = self.main.type_box.get_active_text() + if at == "Compositions" and type != -1: + return False + elif at == "All Bricks" and type == -1: + return False + elif at == "Melody Bricks" and type != 0: + return False + elif at == "Rhythm Bricks" and type != 2: + return False + + a = self.main.scale_box.get_active() + if a == 0: + return True + elif a-1 != scale: + return False + return True + + def writeline_cb(self, line): + self.stream.writelines(line + "\n") + + def makesure_file_on_local(self, filename): + try: + file = open("myscore/" + filename) + except IOError: + if self.main.ftp_status == 1: + try: + self.stream = open("myscore/" + filename, 'w') + msg = self.main.ftp.retrlines("RETR " + filename, self.writeline_cb) + print "ftp::RETR " + filename + "...." + msg + self.stream.close() + except IOError: + return False + else: + return True + else: + return True + + def update_all_list(self): + score = self.main.score + try: + score.srv_brick_list = self.main.ftp.nlst("*.mp*") + except: + score.srv_brick_list = [] + self.main.ftp_status = 0 + score.create_local_brick_list() + + size1 = len(score.local_brick_list) + size2 = len(score.srv_brick_list) + + for i in range(size1): + try: + self.all_brick_list.index(score.local_brick_list[i]) + except ValueError: + self.all_brick_list.append(score.local_brick_list[i]) + + for i in range(size2): + try: + self.all_brick_list.index(score.srv_brick_list[i]) + except ValueError: + self.all_brick_list.append(score.srv_brick_list[i]) + self.combo_changed(self.widget) + + def create_all_list(self): + if not self.main.update_author: + self.update_author_list() + self.main.update_author = True + score = self.main.score + + self.active_brick_list = [] + for i in range(score.work_bricks_cnt): + self.active_brick_list.append(score.work_bricks[i].filename) + for i in range(score.mymelody_bricks_cnt): + self.active_brick_list.append(score.mymelody_bricks[i].filename) + for i in range(score.myrhythm_bricks_cnt): + self.active_brick_list.append(score.myrhythm_bricks[i].filename) + for i in range(score.cmelody_bricks_cnt): + self.active_brick_list.append(score.cmelody_bricks[i].filename) + for i in range(score.crhythm_bricks_cnt): + self.active_brick_list.append(score.crhythm_bricks[i].filename) + + self.all_brick_list = [] + size1 = len(score.local_brick_list) + size2 = len(score.srv_brick_list) + print str(size1) + " files on local, " + str(size2) + " files on server" + self.list = [] + for i in range(size1): + self.all_brick_list.append(score.local_brick_list[i]) + + for i in range(size2): + flag = 0 + for j in range(len(self.all_brick_list)): + if self.all_brick_list[j] == score.srv_brick_list[i]: + flag = 1 + break + if flag == 0: + self.all_brick_list.append(score.srv_brick_list[i]) + + t = len(self.all_brick_list) + for i in range(t * 10): + a = random.randint(0, t-1) + b = random.randint(0, t-1) + f = self.all_brick_list[a] + self.all_brick_list[a] = self.all_brick_list[b] + self.all_brick_list[b] = f + + def change_status(self, name, new_state): + try: + id = self.list.index(name) + except ValueError: + return + else: + self.listf[id] = new_state + + def create_list(self): + size = len(self.all_brick_list) + self.list = [] + self.listf = [] + for i in range(size): + if self.filter(self.all_brick_list[i]): + self.list.append(self.all_brick_list[i]) + try: + id = self.active_brick_list.index(self.all_brick_list[i]) + except ValueError: + self.listf.append(0) # not in list + else: + self.listf.append(1) # in active list + + def lucky_pick(self): # automatically generate collected brick list + score = self.main.score + size = len(self.all_brick_list) + cnt = 0 + while score.cmelody_bricks_cnt < 5: + cnt = cnt + 1 + if cnt > 200: + break + a = random.randint(0, size-1) + name = self.all_brick_list[a] + [author, type, scale] = self.get_file_info(name) + if author == "invalid_filename" or author == self.main.username or type != 0: + continue + try: + id = self.active_brick_list.index(name) + except ValueError: + self.makesure_file_on_local(name) + self.active_brick_list.append(name) + score.cmelody_bricks[score.cmelody_bricks_cnt].read_score(name, score) + score.cmelody_bricks_cnt = score.cmelody_bricks_cnt + 1 + cnt = 0 + while score.crhythm_bricks_cnt < 5: + cnt = cnt + 1 + if cnt > 200: + break + a = random.randint(0, size-1) + name = self.all_brick_list[a] + [author, type, scale] = self.get_file_info(name) + if author == "invalid_filename" or author == self.main.username or type != 2: + continue + try: + id = self.active_brick_list.index(name) + except ValueError: + self.makesure_file_on_local(name) + self.active_brick_list.append(name) + score.crhythm_bricks[score.crhythm_bricks_cnt].read_score(name, score) + score.crhythm_bricks_cnt = score.crhythm_bricks_cnt + 1 + + def load_temp_list_1page(self): + size = len(self.list) + score = self.main.score + score.temp_bricks_cnt = 0 + if self.list_p == 0: + t = size + t2 = 0 + else: + t = size - self.page_cnt[self.list_p-1] + t2 = self.page_cnt[self.list_p-1] + for i in range(t): + self.makesure_file_on_local(self.list[t2+i]) + score.temp_bricks[i].read_score(self.list[t2+i], score) + score.temp_bricks_cnt = score.temp_bricks_cnt + 1 + if i == score.tesize - 1: + break + + def load_temp_list(self): + self.create_list() + self.list_p = 0 + self.load_temp_list_1page() |