mirage.py 201 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587
  1. # $HeadURL: http://svn.berlios.de/svnroot/repos/mirageiv/branches/mirage-0.9.x/mirage.py $
  2. # $Id: mirage.py 337 2011-02-13 22:40:05Z fredricj $
  3. __version__ = "0.9.5.2"
  4. __license__ = """
  5. Mirage, a fast GTK+ Image Viewer
  6. Copyright 2007 Scott Horowitz <stonecrest@gmail.com>
  7. This file is part of Mirage.
  8. Mirage is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 3 of the License, or
  11. (at your option) any later version.
  12. Mirage is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. """
  19. import pygtk
  20. pygtk.require('2.0')
  21. import gtk
  22. import os, sys, getopt, ConfigParser, string, gc
  23. import random, urllib, gobject, gettext, locale
  24. import stat, time, subprocess, shutil, filecmp
  25. import tempfile, socket, threading
  26. try:
  27. import hashlib
  28. HAS_HASHLIB = True
  29. except:
  30. HAS_HASHLIB= False
  31. import md5
  32. try:
  33. import imgfuncs
  34. HAS_IMGFUNCS = True
  35. except:
  36. HAS_IMGFUNCS = False
  37. print "imgfuncs.so module not found, rotating/flipping images will be disabled."
  38. try:
  39. import xmouse
  40. HAS_XMOUSE = True
  41. except:
  42. HAS_XMOUSE = False
  43. print "xmouse.so module not found, some screenshot capabilities will be disabled."
  44. try:
  45. import gconf
  46. except:
  47. pass
  48. if gtk.gtk_version < (2, 10, 0):
  49. sys.stderr.write("Mirage, GTK + 2.10.0 veya daha yeni bir sürüm gerektirir..\n")
  50. sys.exit(1)
  51. if gtk.pygtk_version < (2, 12, 0):
  52. sys.stderr.write("Mirage PyGTK 2.12.0 veya daha yeni bir sürümünü gerektirir.\n")
  53. sys.exit(1)
  54. def valid_int(inputstring):
  55. try:
  56. x = int(inputstring)
  57. return True
  58. except:
  59. return False
  60. class Base:
  61. def __init__(self):
  62. import glib
  63. if glib.glib_version < (2, 41, 0):
  64. gtk.gdk.threads_init()
  65. # FIX THIS! Does not work on windows and what happens if mo-files exists
  66. # in both dirs?
  67. gettext.install('mirage', '/usr/share/locale', unicode=1)
  68. gettext.install('mirage', '/usr/local/share/locale', unicode=1)
  69. # Constants
  70. self.open_mode_smart = 0
  71. self.open_mode_fit = 1
  72. self.open_mode_1to1 = 2
  73. self.open_mode_last = 3
  74. self.min_zoomratio = 0.02
  75. # Initialize vars:
  76. width=600
  77. height=400
  78. bgcolor_found = False
  79. self.simple_bgcolor = False
  80. # Current image:
  81. self.curr_img_in_list = 0
  82. self.currimg_name = ""
  83. self.currimg_width = 0
  84. self.currimg_height = 0
  85. self.currimg_pixbuf = None
  86. self.currimg_pixbuf_original = None
  87. self.currimg_zoomratio = 1
  88. self.currimg_is_animation = False
  89. # This is the actual pixbuf that is loaded in Mirage. This will
  90. # usually be the same as self.curr_img_in_list except for scenarios
  91. # like when the user presses 'next image' multiple times in a row.
  92. # In this case, self.curr_img_in_list will increment while
  93. # self.loaded_img_in_list will retain the current loaded image.
  94. self.loaded_img_in_list = 0
  95. # Next preloaded image:
  96. self.preloadimg_next_in_list = -1
  97. self.preloadimg_next_name = ""
  98. self.preloadimg_next_width = 0
  99. self.preloadimg_next_height = 0
  100. self.preloadimg_next_pixbuf = None
  101. self.preloadimg_next_pixbuf_original = None
  102. self.preloadimg_next_zoomratio = 1
  103. self.preloadimg_next_is_animation = False
  104. # Previous preloaded image:
  105. self.preloadimg_prev_in_list = -1
  106. self.preloadimg_prev_name = ""
  107. self.preloadimg_prev_width = 0
  108. self.preloadimg_prev_height = 0
  109. self.preloadimg_prev_pixbuf = None
  110. self.preloadimg_prev_pixbuf_original = None
  111. self.preloadimg_prev_zoomratio = 1
  112. self.preloadimg_prev_is_animation = False
  113. # Settings, misc:
  114. self.toolbar_show = True
  115. self.thumbpane_show = True
  116. self.statusbar_show = True
  117. self.fullscreen_mode = False
  118. self.opendialogpath = ""
  119. self.zoom_quality = gtk.gdk.INTERP_BILINEAR
  120. self.recursive = False
  121. self.verbose = False
  122. self.image_loaded = False
  123. self.open_all_images = True # open all images in the directory(ies)
  124. self.use_last_dir = True
  125. self.last_dir = os.path.expanduser("~")
  126. self.fixed_dir = os.path.expanduser("~")
  127. self.image_list = []
  128. self.open_mode = self.open_mode_smart
  129. self.last_mode = self.open_mode_smart
  130. self.listwrap_mode = 0 # 0=no, 1=yes, 2=ask
  131. self.user_prompt_visible = False # the "wrap?" prompt
  132. self.slideshow_delay = 1 # seconds
  133. self.slideshow_mode = False
  134. self.slideshow_random = False
  135. self.slideshow_controls_visible = False # fullscreen slideshow controls
  136. self.controls_moving = False
  137. self.zoomvalue = 2
  138. self.quality_save = 90
  139. self.updating_adjustments = False
  140. self.disable_screensaver = False
  141. self.slideshow_in_fullscreen = False
  142. self.closing_app = False
  143. self.confirm_delete = True
  144. self.preloading_images = True
  145. self.action_names = ["GIMP'te AÇ", "Küçük Resim Oluştur", "Küçük Resim Oluştur", "Favorilere Gönder"]
  146. self.action_shortcuts = ["<Control>e", "<Alt>t", "<Control><Alt>t", "<Control><Alt>f"]
  147. self.action_commands = ["gimp-remote-2.4 %F", "convert %F -thumbnail 150x150 %Pt_%N.jpg", "convert %F -thumbnail 150x150 %Pt_%N.jpg", "mkdir -p ~/mirage-favs; mv %F ~/mirage-favs; [NEXT]"]
  148. self.action_batch = [False, False, True, False]
  149. self.onload_cmd = None
  150. self.searching_for_images = False
  151. self.preserve_aspect = True
  152. self.ignore_preserve_aspect_callback = False
  153. self.savemode = 2
  154. self.image_modified = False
  155. self.image_zoomed = False
  156. self.start_in_fullscreen = False
  157. self.running_custom_actions = False
  158. self.merge_id = None
  159. self.actionGroupCustom = None
  160. self.merge_id_recent = None
  161. self.actionGroupRecent = None
  162. self.open_hidden_files = False
  163. self.thumbnail_sizes = ["128", "96", "72", "64", "48", "32"]
  164. self.thumbnail_size = 128 # Default to 128 x 128
  165. self.thumbnail_loaded = []
  166. self.thumbpane_updating = False
  167. self.recentfiles = ["", "", "", "", ""]
  168. self.screenshot_delay = 2
  169. self.thumbpane_bottom_coord_loaded = 0
  170. # Read any passed options/arguments:
  171. try:
  172. opts, args = getopt.getopt(sys.argv[1:], "hRvVsfo:", ["help", "version", "recursive", "verbose", "slideshow", "fullscreen", "onload="])
  173. except getopt.GetoptError:
  174. # print help information and exit:
  175. self.print_usage()
  176. sys.exit(2)
  177. # If options were passed, perform action on them.
  178. if opts != []:
  179. for o, a in opts:
  180. if o in ("-v", "--version"):
  181. self.print_version()
  182. sys.exit(2)
  183. elif o in ("-h", "--help"):
  184. self.print_usage()
  185. sys.exit(2)
  186. elif o in ("-R", "--recursive"):
  187. self.recursive = True
  188. elif o in ("-V", "--verbose"):
  189. self.verbose = True
  190. elif o in ("-s", "--slideshow", "-f", "--fullscreen"):
  191. #This will be handled later
  192. None
  193. elif o in ("-o", "--onload"):
  194. self.onload_cmd = a
  195. else:
  196. self.print_usage()
  197. sys.exit(2)
  198. # Determine config dir, first try the environment variable XDG_CONFIG_HOME
  199. # according to XDG specification and as a fallback use ~/.config/mirage
  200. self.config_dir = (os.getenv('XDG_CONFIG_HOME') or os.path.expanduser('~/.config')) + '/mirage'
  201. # Load config from disk:
  202. conf = ConfigParser.ConfigParser()
  203. if os.path.isfile(self.config_dir + '/miragerc'):
  204. conf.read(self.config_dir + '/miragerc')
  205. if conf.has_option('window', 'w'):
  206. width = conf.getint('window', 'w')
  207. if conf.has_option('window', 'h'):
  208. height = conf.getint('window', 'h')
  209. if conf.has_option('window', 'toolbar'):
  210. self.toolbar_show = conf.getboolean('window', 'toolbar')
  211. if conf.has_option('window', 'statusbar'):
  212. self.statusbar_show = conf.getboolean('window', 'statusbar')
  213. if conf.has_option('window', 'thumbpane'):
  214. self.thumbpane_show = conf.getboolean('window', 'thumbpane')
  215. if conf.has_option('prefs', 'simple-bgcolor'):
  216. self.simple_bgcolor = conf.getboolean('prefs', 'simple-bgcolor')
  217. if conf.has_option('prefs', 'bgcolor-red'):
  218. bgr = conf.getint('prefs', 'bgcolor-red')
  219. bgg = conf.getint('prefs', 'bgcolor-green')
  220. bgb = conf.getint('prefs', 'bgcolor-blue')
  221. bgcolor_found = True
  222. self.bgcolor = gtk.gdk.Color(red=bgr, green=bgg, blue=bgb)
  223. if conf.has_option('prefs', 'use_last_dir'):
  224. self.use_last_dir = conf.getboolean('prefs', 'use_last_dir')
  225. if conf.has_option('prefs', 'last_dir'):
  226. self.last_dir = conf.get('prefs', 'last_dir')
  227. if conf.has_option('prefs', 'fixed_dir'):
  228. self.fixed_dir = conf.get('prefs', 'fixed_dir')
  229. if conf.has_option('prefs', 'open_all'):
  230. self.open_all_images = conf.getboolean('prefs', 'open_all')
  231. if conf.has_option('prefs', 'hidden'):
  232. self.open_hidden_files = conf.getboolean('prefs', 'hidden')
  233. if conf.has_option('prefs', 'open_mode'):
  234. self.open_mode = conf.getint('prefs', 'open_mode')
  235. if conf.has_option('prefs', 'last_mode'):
  236. self.last_mode = conf.getint('prefs', 'last_mode')
  237. if conf.has_option('prefs', 'listwrap_mode'):
  238. self.listwrap_mode = conf.getint('prefs', 'listwrap_mode')
  239. if conf.has_option('prefs', 'slideshow_delay'):
  240. self.slideshow_delay = conf.getint('prefs', 'slideshow_delay')
  241. if conf.has_option('prefs', 'slideshow_random'):
  242. self.slideshow_random = conf.getboolean('prefs', 'slideshow_random')
  243. if conf.has_option('prefs', 'zoomquality'):
  244. self.zoomvalue = conf.getint('prefs', 'zoomquality')
  245. if int(round(self.zoomvalue, 0)) == 0:
  246. self.zoom_quality = gtk.gdk.INTERP_NEAREST
  247. elif int(round(self.zoomvalue, 0)) == 1:
  248. self.zoom_quality = gtk.gdk.INTERP_TILES
  249. elif int(round(self.zoomvalue, 0)) == 2:
  250. self.zoom_quality = gtk.gdk.INTERP_BILINEAR
  251. elif int(round(self.zoomvalue, 0)) == 3:
  252. self.zoom_quality = gtk.gdk.INTERP_HYPER
  253. if conf.has_option('prefs', 'quality_save'):
  254. self.quality_save = conf.getint('prefs', 'quality_save')
  255. if conf.has_option('prefs', 'disable_screensaver'):
  256. self.disable_screensaver = conf.getboolean('prefs', 'disable_screensaver')
  257. if conf.has_option('prefs', 'slideshow_in_fullscreen'):
  258. self.slideshow_in_fullscreen = conf.getboolean('prefs', 'slideshow_in_fullscreen')
  259. if conf.has_option('prefs', 'preloading_images'):
  260. self.preloading_images = conf.getboolean('prefs', 'preloading_images')
  261. if conf.has_option('prefs', 'thumbsize'):
  262. self.thumbnail_size = conf.getint('prefs', 'thumbsize')
  263. if conf.has_option('prefs', 'screenshot_delay'):
  264. self.screenshot_delay = conf.getint('prefs', 'screenshot_delay')
  265. if conf.has_option('actions', 'num_actions'):
  266. num_actions = conf.getint('actions', 'num_actions')
  267. self.action_names = []
  268. self.action_commands = []
  269. self.action_shortcuts = []
  270. self.action_batch = []
  271. for i in range(num_actions):
  272. if conf.has_option('actions', 'names[' + str(i) + ']') and conf.has_option('actions', 'commands[' + str(i) + ']') and conf.has_option('actions', 'shortcuts[' + str(i) + ']') and conf.has_option('actions', 'batch[' + str(i) + ']'):
  273. self.action_names.append(conf.get('actions', 'names[' + str(i) + ']'))
  274. self.action_commands.append(conf.get('actions', 'commands[' + str(i) + ']'))
  275. self.action_shortcuts.append(conf.get('actions', 'shortcuts[' + str(i) + ']'))
  276. self.action_batch.append(conf.getboolean('actions', 'batch[' + str(i) + ']'))
  277. if conf.has_option('prefs', 'savemode'):
  278. self.savemode = conf.getint('prefs', 'savemode')
  279. if conf.has_option('prefs', 'start_in_fullscreen'):
  280. self.start_in_fullscreen = conf.getboolean('prefs', 'start_in_fullscreen')
  281. if conf.has_option('prefs', 'confirm_delete'):
  282. self.confirm_delete = conf.getboolean('prefs', 'confirm_delete')
  283. self.recentfiles = []
  284. if conf.has_option('recent', 'num_recent'):
  285. num_recent = conf.getint('recent', 'num_recent')
  286. for i in range(num_recent):
  287. self.recentfiles.append('')
  288. if conf.has_option('recent', 'urls[' + str(i) + ',0]'):
  289. self.recentfiles[i] = conf.get('recent', 'urls[' + str(i) + ',0]')
  290. # slideshow_delay is the user's preference, whereas curr_slideshow_delay is
  291. # the current delay (which can be changed without affecting the 'default')
  292. self.curr_slideshow_delay = self.slideshow_delay
  293. # Same for randomization:
  294. self.curr_slideshow_random = self.slideshow_random
  295. # Read accel_map file, if it exists
  296. if os.path.isfile(self.config_dir + '/accel_map'):
  297. gtk.accel_map_load(self.config_dir + '/accel_map')
  298. # Directory/ies in which to find application images/pixmaps
  299. self.resource_path_list = False
  300. self.blank_image = gtk.gdk.pixbuf_new_from_file(self.find_path("mirage_blank.png"))
  301. # Define the main menubar and toolbar:
  302. factory = gtk.IconFactory()
  303. iconname = 'stock_leave-fullscreen.png'
  304. iconname2 = 'stock_fullscreen.png'
  305. leave_fullscreen_icon_path = self.find_path(iconname)
  306. pixbuf = gtk.gdk.pixbuf_new_from_file(leave_fullscreen_icon_path)
  307. iconset = gtk.IconSet(pixbuf)
  308. factory.add('leave-fullscreen', iconset)
  309. factory.add_default()
  310. fullscreen_icon_path = self.find_path(iconname2)
  311. pixbuf = gtk.gdk.pixbuf_new_from_file(fullscreen_icon_path)
  312. iconset = gtk.IconSet(pixbuf)
  313. factory.add('fullscreen', iconset)
  314. factory.add_default()
  315. try:
  316. test = gtk.Button("", gtk.STOCK_LEAVE_FULLSCREEN)
  317. leave_fullscreen_icon = gtk.STOCK_LEAVE_FULLSCREEN
  318. fullscreen_icon = gtk.STOCK_FULLSCREEN
  319. except:
  320. # This will allow gtk 2.6 users to run Mirage
  321. leave_fullscreen_icon = 'leave-fullscreen'
  322. fullscreen_icon = 'fullscreen'
  323. actions = (
  324. ('FileMenu', None, _('_Dosya')),
  325. ('EditMenu', None, _('_Düzen')),
  326. ('ViewMenu', None, _('_Görünüm')),
  327. ('GoMenu', None, _('_Git')),
  328. ('HelpMenu', None, _('_Yardım')),
  329. ('ActionSubMenu', None, _('Özel Eylemler')),
  330. ('Open Image', gtk.STOCK_FILE, _('_Resim Aç...'), '<Ctrl>O', _('Resim Aç'), self.open_file),
  331. ('Open Remote Image', gtk.STOCK_NETWORK, _('Uzak Resim Aç...'), None, _('Uzak Resim Aç'), self.open_file_remote),
  332. ('Open Folder', gtk.STOCK_DIRECTORY, _('Klasör Aç...'), '<Ctrl>F', _('Klasör Aç'), self.open_folder),
  333. ('Save', gtk.STOCK_SAVE, _('_Resmi Kaydet'), '<Ctrl>S', _('Resmi Kaydet'), self.save_image),
  334. ('Save As', gtk.STOCK_SAVE, _('Resmi Farklı Kaydet...'), '<Shift><Ctrl>S', _('Resmi Farklı Kaydet'), self.save_image_as),
  335. ('Crop', None, _('_Kırp...'), None, _('Resmi Kırp'), self.crop_image),
  336. ('Resize', None, _('Yeniden Boyutlandır...'), None, _('Resmi Yeniden Boyutlandır'), self.resize_image),
  337. ('Saturation', None, _('_Doygunluğu Değiştir...'), None, _('Doygunluğu Değiştir'), self.saturation),
  338. ('Quit', gtk.STOCK_QUIT, _('_Çıkış'), '<Ctrl>Q', _('Çıkış'), self.exit_app),
  339. ('Previous Image', gtk.STOCK_GO_BACK, _('_Önceki Resim'), 'Left', _('Önceki Resim'), self.goto_prev_image),
  340. ('Next Image', gtk.STOCK_GO_FORWARD, _('_Sonraki Resim'), 'Right', _('Sonraki Resim'), self.goto_next_image),
  341. ('Previous2', gtk.STOCK_GO_BACK, _('_Önceki'), 'Left', _('Önceki'), self.goto_prev_image),
  342. ('Next2', gtk.STOCK_GO_FORWARD, _('_Sonraki'), 'Right', _('Sonraki'), self.goto_next_image),
  343. ('Random Image', None, _('_Rastgele Resim'), 'R', _('Rastgele Resim'), self.goto_random_image),
  344. ('First Image', gtk.STOCK_GOTO_FIRST, _('_İlk Resim'), 'Home', _('İlk Resim'), self.goto_first_image),
  345. ('Last Image', gtk.STOCK_GOTO_LAST, _('_Son Resim'), 'End', _('Son Resim'), self.goto_last_image),
  346. ('In', gtk.STOCK_ZOOM_IN, _('Yakınlaştır'), '<Ctrl>Up', _('Yakınlaştır'), self.zoom_in),
  347. ('Out', gtk.STOCK_ZOOM_OUT, _('Uzaklaştır'), '<Ctrl>Down', _('Uzaklaştır'), self.zoom_out),
  348. ('Fit', gtk.STOCK_ZOOM_FIT, _('Uygun Boyut'), '<Ctrl>0', _('Uygun Boyut'), self.zoom_to_fit_window_action),
  349. ('1:1', gtk.STOCK_ZOOM_100, _('_1:1'), '<Ctrl>1', _('1:1'), self.zoom_1_to_1_action),
  350. ('Rotate Left', None, _('_Sola Döndür'), '<Ctrl>Left', _('Sola Döndür'), self.rotate_left),
  351. ('Rotate Right', None, _('_Sağa Döndür'), '<Ctrl>Right', _('Sağa Döndür'), self.rotate_right),
  352. ('Flip Vertically', None, _('_Dikey Çevir'), '<Ctrl>V', _('Dikey Çevir'), self.flip_image_vert),
  353. ('Flip Horizontally', None, _('_Yatay Çevir'), '<Ctrl>H', _('Yatay Çevir'), self.flip_image_horiz),
  354. ('About', gtk.STOCK_ABOUT, _('_Hakkında'), None, _('Hakkında'), self.show_about),
  355. ('Contents', gtk.STOCK_HELP, _('_İçerik'), 'F1', _('İçerik'), self.show_help),
  356. ('Preferences', gtk.STOCK_PREFERENCES, _('_Seçenekler...'), '<Ctrl>P', _('Seçenekler'), self.show_prefs),
  357. ('Full Screen', fullscreen_icon, _('_Tam Ekran'), 'F11', _('Tam Ekran'), self.enter_fullscreen),
  358. ('Exit Full Screen', leave_fullscreen_icon, _('_Tam Ekrandan Çık'), None, _('Tam Ekrandan Çık'), self.leave_fullscreen),
  359. ('Start Slideshow', gtk.STOCK_MEDIA_PLAY, _('_Slayt Gösterisi Başlat'), 'F5', _('Slayt Gösterisi Başlat'), self.toggle_slideshow),
  360. ('Stop Slideshow', gtk.STOCK_MEDIA_STOP, _('_Slayt Gösterisini Durdur'), 'F5', _('Slayt Gösterisini Durdur'), self.toggle_slideshow),
  361. ('Delete Image', gtk.STOCK_DELETE, _('_Sil...'), 'Delete', _('Resmi Sil'), self.delete_image),
  362. ('Rename Image', None, _('Yeniden Adlandır...'), 'F2', _('Resmi Yeniden Adlandır'), self.rename_image),
  363. ('Take Screenshot', None, _('_Ekran Resmi Al...'), None, _('Ekran Resmi Al'), self.screenshot),
  364. ('Properties', gtk.STOCK_PROPERTIES, _('Seçenekler...'), None, _('Seçenekler'), self.show_properties),
  365. ('Custom Actions', None, _('_Ayarla...'), None, _('Özel Eylemler'), self.show_custom_actions),
  366. ('MiscKeysMenuHidden', None, 'Keys'),
  367. ('Escape', None, '', 'Escape', _('Tam Ekrandan Çık'), self.leave_fullscreen),
  368. ('Minus', None, '', 'minus', _('Uzaklaştır'), self.zoom_out),
  369. ('Plus', None, '', 'plus', _('Yakınlaştır'), self.zoom_in),
  370. ('Equal', None, '', 'equal', _('Yakınlaştır'), self.zoom_in),
  371. ('Space', None, '', 'space', _('Sonraki Resim'), self.goto_next_image),
  372. ('Ctrl-KP_Insert', None, '', '<Ctrl>KP_Insert', _('Uygun Boyut'), self.zoom_to_fit_window_action),
  373. ('Ctrl-KP_End', None, '', '<Ctrl>KP_End', _('1:1'), self.zoom_1_to_1_action),
  374. ('Ctrl-KP_Subtract', None, '', '<Ctrl>KP_Subtract', _('Uzaklaştır'), self.zoom_out),
  375. ('Ctrl-KP_Add', None, '', '<Ctrl>KP_Add', _('Yakınlaştır'), self.zoom_in),
  376. ('Ctrl-KP_0', None, '', '<Ctrl>KP_0', _('Uygun Boyut'), self.zoom_to_fit_window_action),
  377. ('Ctrl-KP_1', None, '', '<Ctrl>KP_1', _('1:1'), self.zoom_1_to_1_action),
  378. ('Full Screen Key', None, '', '<Shift>Return', None, self.enter_fullscreen),
  379. ('Prev', None, '', 'Up', _('Önceki Resim'), self.goto_prev_image),
  380. ('Next', None, '', 'Down', _('Sonraki Resim'), self.goto_next_image),
  381. ('PgUp', None, '', 'Page_Up', _('Önceki Resim'), self.goto_prev_image),
  382. ('PgDn', None, '', 'Page_Down', _('Sonraki Resim'), self.goto_next_image),
  383. ('BackSpace', None, '', 'BackSpace', _('Previous Image'), self.goto_prev_image),
  384. ('OriginalSize', None, '', '1', _('1:1'), self.zoom_1_to_1_action),
  385. ('ZoomIn', None, '', 'KP_Add', _('Yakınlaştır'), self.zoom_in),
  386. ('ZoomOut', None, '', 'KP_Subtract', _('Uzaklaştır'), self.zoom_out)
  387. )
  388. toggle_actions = (
  389. ('Status Bar', None, _('_Durum Çubuğu'), None, _('Durum Çubuğu'), self.toggle_status_bar, self.statusbar_show),
  390. ('Toolbar', None, _('_Araç Çubuğu'), None, _('Araç Çubuğu'), self.toggle_toolbar, self.toolbar_show),
  391. ('Thumbnails Pane', None, _('Küçük Resim Bölümü'), None, _('Küçük Resim Bölümü'), self.toggle_thumbpane, self.thumbpane_show)
  392. )
  393. # Populate keys[]:
  394. self.keys=[]
  395. for i in range(len(actions)):
  396. if len(actions[i]) > 3:
  397. if actions[i][3] != None:
  398. self.keys.append([actions[i][4], actions[i][3]])
  399. uiDescription = """
  400. <ui>
  401. <popup name="Popup">
  402. <menuitem action="Next Image"/>
  403. <menuitem action="Previous Image"/>
  404. <separator name="FM1"/>
  405. <menuitem action="Out"/>
  406. <menuitem action="In"/>
  407. <menuitem action="1:1"/>
  408. <menuitem action="Fit"/>
  409. <separator name="FM4"/>
  410. <menuitem action="Start Slideshow"/>
  411. <menuitem action="Stop Slideshow"/>
  412. <separator name="FM3"/>
  413. <menuitem action="Exit Full Screen"/>
  414. <menuitem action="Full Screen"/>
  415. </popup>
  416. <menubar name="MainMenu">
  417. <menu action="FileMenu">
  418. <menuitem action="Open Image"/>
  419. <menuitem action="Open Folder"/>
  420. <menuitem action="Open Remote Image"/>
  421. <separator name="FM1"/>
  422. <menuitem action="Save"/>
  423. <menuitem action="Save As"/>
  424. <separator name="FM2"/>
  425. <menuitem action="Take Screenshot"/>
  426. <separator name="FM3"/>
  427. <menuitem action="Properties"/>
  428. <separator name="FM4"/>
  429. <placeholder name="Recent Files">
  430. </placeholder>
  431. <separator name="FM5"/>
  432. <menuitem action="Quit"/>
  433. </menu>
  434. <menu action="EditMenu">
  435. <menuitem action="Rotate Left"/>
  436. <menuitem action="Rotate Right"/>
  437. <menuitem action="Flip Vertically"/>
  438. <menuitem action="Flip Horizontally"/>
  439. <separator name="FM1"/>
  440. <menuitem action="Crop"/>
  441. <menuitem action="Resize"/>
  442. <menuitem action="Saturation"/>
  443. <separator name="FM2"/>
  444. <menuitem action="Rename Image"/>
  445. <menuitem action="Delete Image"/>
  446. <separator name="FM3"/>
  447. <menu action="ActionSubMenu">
  448. <separator name="FM4" position="bot"/>
  449. <menuitem action="Custom Actions" position="bot"/>
  450. </menu>
  451. <menuitem action="Preferences"/>
  452. </menu>
  453. <menu action="ViewMenu">
  454. <menuitem action="Out"/>
  455. <menuitem action="In"/>
  456. <menuitem action="1:1"/>
  457. <menuitem action="Fit"/>
  458. <separator name="FM2"/>
  459. <menuitem action="Toolbar"/>
  460. <menuitem action="Thumbnails Pane"/>
  461. <menuitem action="Status Bar"/>
  462. <separator name="FM1"/>
  463. <menuitem action="Full Screen"/>
  464. </menu>
  465. <menu action="GoMenu">
  466. <menuitem action="Next Image"/>
  467. <menuitem action="Previous Image"/>
  468. <menuitem action="Random Image"/>
  469. <separator name="FM1"/>
  470. <menuitem action="First Image"/>
  471. <menuitem action="Last Image"/>
  472. <separator name="FM2"/>
  473. <menuitem action="Start Slideshow"/>
  474. <menuitem action="Stop Slideshow"/>
  475. </menu>
  476. <menu action="HelpMenu">
  477. <menuitem action="Contents"/>
  478. <menuitem action="About"/>
  479. </menu>
  480. <menu action="MiscKeysMenuHidden">
  481. <menuitem action="Minus"/>
  482. <menuitem action="Escape"/>
  483. <menuitem action="Plus"/>
  484. <menuitem action="Equal"/>
  485. <menuitem action="Space"/>
  486. <menuitem action="Ctrl-KP_Insert"/>
  487. <menuitem action="Ctrl-KP_End"/>
  488. <menuitem action="Ctrl-KP_Subtract"/>
  489. <menuitem action="Ctrl-KP_Add"/>
  490. <menuitem action="Ctrl-KP_0"/>
  491. <menuitem action="Ctrl-KP_1"/>
  492. <menuitem action="Full Screen Key"/>
  493. <menuitem action="Prev"/>
  494. <menuitem action="Next"/>
  495. <menuitem action="PgUp"/>
  496. <menuitem action="PgDn"/>
  497. <menuitem action="OriginalSize"/>
  498. <menuitem action="BackSpace"/>
  499. <menuitem action="ZoomIn"/>
  500. <menuitem action="ZoomOut"/>
  501. </menu>
  502. </menubar>
  503. <toolbar name="MainToolbar">
  504. <toolitem action="Open Image"/>
  505. <separator name="FM1"/>
  506. <toolitem action="Previous2"/>
  507. <toolitem action="Next2"/>
  508. <separator name="FM2"/>
  509. <toolitem action="Out"/>
  510. <toolitem action="In"/>
  511. <toolitem action="1:1"/>
  512. <toolitem action="Fit"/>
  513. </toolbar>
  514. </ui>
  515. """
  516. # Create interface
  517. self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  518. self.update_title()
  519. icon_path = self.find_path('mirage.png')
  520. try:
  521. gtk.window_set_default_icon_from_file(icon_path)
  522. except:
  523. pass
  524. vbox = gtk.VBox(False, 0)
  525. self.UIManager = gtk.UIManager()
  526. actionGroup = gtk.ActionGroup('Actions')
  527. actionGroup.add_actions(actions)
  528. actionGroup.add_toggle_actions(toggle_actions)
  529. self.UIManager.insert_action_group(actionGroup, 0)
  530. self.UIManager.add_ui_from_string(uiDescription)
  531. self.refresh_custom_actions_menu()
  532. self.refresh_recent_files_menu()
  533. self.window.add_accel_group(self.UIManager.get_accel_group())
  534. self.menubar = self.UIManager.get_widget('/MainMenu')
  535. vbox.pack_start(self.menubar, False, False, 0)
  536. self.toolbar = self.UIManager.get_widget('/MainToolbar')
  537. vbox.pack_start(self.toolbar, False, False, 0)
  538. self.layout = gtk.Layout()
  539. self.vscroll = gtk.VScrollbar(None)
  540. self.vscroll.set_adjustment(self.layout.get_vadjustment())
  541. self.hscroll = gtk.HScrollbar(None)
  542. self.hscroll.set_adjustment(self.layout.get_hadjustment())
  543. self.table = gtk.Table(3, 2, False)
  544. self.thumblist = gtk.ListStore(gtk.gdk.Pixbuf)
  545. self.thumbpane = gtk.TreeView(self.thumblist)
  546. self.thumbcolumn = gtk.TreeViewColumn(None)
  547. self.thumbcell = gtk.CellRendererPixbuf()
  548. self.thumbcolumn.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
  549. self.thumbpane_set_size()
  550. self.thumbpane.append_column(self.thumbcolumn)
  551. self.thumbcolumn.pack_start(self.thumbcell, True)
  552. self.thumbcolumn.set_attributes(self.thumbcell, pixbuf=0)
  553. self.thumbpane.get_selection().set_mode(gtk.SELECTION_SINGLE)
  554. self.thumbpane.set_headers_visible(False)
  555. self.thumbpane.set_property('can-focus', False)
  556. self.thumbscroll = gtk.ScrolledWindow()
  557. self.thumbscroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
  558. self.thumbscroll.add(self.thumbpane)
  559. self.table.attach(self.thumbscroll, 0, 1, 0, 1, 0, gtk.FILL|gtk.EXPAND, 0, 0)
  560. self.table.attach(self.layout, 1, 2, 0, 1, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  561. self.table.attach(self.hscroll, 1, 2, 1, 2, gtk.FILL|gtk.SHRINK, gtk.FILL|gtk.SHRINK, 0, 0)
  562. self.table.attach(self.vscroll, 2, 3, 0, 1, gtk.FILL|gtk.SHRINK, gtk.FILL|gtk.SHRINK, 0, 0)
  563. vbox.pack_start(self.table, True, True, 0)
  564. if not bgcolor_found:
  565. self.bgcolor = gtk.gdk.Color(0, 0, 0) # Default to black
  566. if self.simple_bgcolor:
  567. self.layout.modify_bg(gtk.STATE_NORMAL, None)
  568. else:
  569. self.layout.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
  570. self.imageview = gtk.Image()
  571. self.layout.add(self.imageview)
  572. self.statusbar = gtk.Statusbar()
  573. self.statusbar2 = gtk.Statusbar()
  574. self.statusbar.set_has_resize_grip(False)
  575. self.statusbar2.set_has_resize_grip(True)
  576. self.statusbar2.set_size_request(200, -1)
  577. hbox_statusbar = gtk.HBox()
  578. hbox_statusbar.pack_start(self.statusbar, expand=True)
  579. hbox_statusbar.pack_start(self.statusbar2, expand=False)
  580. vbox.pack_start(hbox_statusbar, False, False, 0)
  581. self.window.add(vbox)
  582. self.window.set_property('allow-shrink', False)
  583. self.window.set_default_size(width,height)
  584. # Slideshow control:
  585. self.slideshow_window = gtk.Window(gtk.WINDOW_POPUP)
  586. self.slideshow_controls = gtk.HBox()
  587. self.ss_back = gtk.Button()
  588. self.ss_back.add(gtk.image_new_from_stock(gtk.STOCK_GO_BACK, gtk.ICON_SIZE_BUTTON))
  589. self.ss_back.set_property('can-focus', False)
  590. self.ss_back.connect('clicked', self.goto_prev_image)
  591. self.ss_start = gtk.Button("", gtk.STOCK_MEDIA_PLAY)
  592. self.ss_start.get_child().get_child().get_children()[1].set_text('')
  593. self.ss_start.set_property('can-focus', False)
  594. self.ss_start.connect('clicked', self.toggle_slideshow)
  595. self.ss_stop = gtk.Button("", gtk.STOCK_MEDIA_STOP)
  596. self.ss_stop.get_child().get_child().get_children()[1].set_text('')
  597. self.ss_stop.set_property('can-focus', False)
  598. self.ss_stop.connect('clicked', self.toggle_slideshow)
  599. self.ss_forward = gtk.Button("", gtk.STOCK_GO_FORWARD)
  600. self.ss_forward.get_child().get_child().get_children()[1].set_text('')
  601. self.ss_forward.set_property('can-focus', False)
  602. self.ss_forward.connect('clicked', self.goto_next_image)
  603. self.slideshow_controls.pack_start(self.ss_back, False, False, 0)
  604. self.slideshow_controls.pack_start(self.ss_start, False, False, 0)
  605. self.slideshow_controls.pack_start(self.ss_stop, False, False, 0)
  606. self.slideshow_controls.pack_start(self.ss_forward, False, False, 0)
  607. self.slideshow_window.add(self.slideshow_controls)
  608. if self.simple_bgcolor:
  609. self.slideshow_window.modify_bg(gtk.STATE_NORMAL, None)
  610. else:
  611. self.slideshow_window.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
  612. self.slideshow_window2 = gtk.Window(gtk.WINDOW_POPUP)
  613. self.slideshow_controls2 = gtk.HBox()
  614. try:
  615. self.ss_exit = gtk.Button("", gtk.STOCK_LEAVE_FULLSCREEN)
  616. self.ss_exit.get_child().get_child().get_children()[1].set_text('')
  617. except:
  618. self.ss_exit = gtk.Button()
  619. self.ss_exit.set_image(gtk.image_new_from_stock('leave-fullscreen', gtk.ICON_SIZE_MENU))
  620. self.ss_exit.set_property('can-focus', False)
  621. self.ss_exit.connect('clicked', self.leave_fullscreen)
  622. self.ss_randomize = gtk.ToggleButton()
  623. icon_path = self.find_path('stock_shuffle.png')
  624. try:
  625. pixbuf = gtk.gdk.pixbuf_new_from_file(icon_path)
  626. iconset = gtk.IconSet(pixbuf)
  627. factory.add('stock-shuffle', iconset)
  628. factory.add_default()
  629. self.ss_randomize.set_image(gtk.image_new_from_stock('stock-shuffle', gtk.ICON_SIZE_MENU))
  630. except:
  631. self.ss_randomize.set_label("Rand")
  632. self.ss_randomize.connect('toggled', self.random_changed)
  633. spin_adj = gtk.Adjustment(self.slideshow_delay, 0, 50000, 1,100, 0)
  634. self.ss_delayspin = gtk.SpinButton(spin_adj, 1.0, 0)
  635. self.ss_delayspin.set_numeric(True)
  636. self.ss_delayspin.connect('changed', self.delay_changed)
  637. self.slideshow_controls2.pack_start(self.ss_randomize, False, False, 0)
  638. self.slideshow_controls2.pack_start(self.ss_delayspin, False, False, 0)
  639. self.slideshow_controls2.pack_start(self.ss_exit, False, False, 0)
  640. self.slideshow_window2.add(self.slideshow_controls2)
  641. if self.simple_bgcolor:
  642. self.slideshow_window2.modify_bg(gtk.STATE_NORMAL, None)
  643. else:
  644. self.slideshow_window2.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
  645. # Connect signals
  646. self.window.connect("delete_event", self.delete_event)
  647. self.window.connect("destroy", self.destroy)
  648. self.window.connect("size-allocate", self.window_resized)
  649. self.window.connect('key-press-event', self.topwindow_keypress)
  650. self.toolbar.connect('focus', self.toolbar_focused)
  651. self.layout.drag_dest_set(gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_DROP, [("text/uri-list", 0, 80)], gtk.gdk.ACTION_DEFAULT)
  652. self.layout.connect('drag_motion', self.motion_cb)
  653. self.layout.connect('drag_data_received', self.drop_cb)
  654. self.layout.add_events(gtk.gdk.KEY_PRESS_MASK | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_MOTION_MASK | gtk.gdk.SCROLL_MASK)
  655. self.layout.connect("scroll-event", self.mousewheel_scrolled)
  656. self.layout.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.KEY_PRESS_MASK)
  657. self.layout.connect("button_press_event", self.button_pressed)
  658. self.layout.add_events(gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK | gtk.gdk.BUTTON_RELEASE_MASK)
  659. self.layout.connect("motion-notify-event", self.mouse_moved)
  660. self.layout.connect("button-release-event", self.button_released)
  661. self.imageview.connect("expose-event", self.expose_event)
  662. self.thumb_sel_handler = self.thumbpane.get_selection().connect('changed', self.thumbpane_selection_changed)
  663. self.thumb_scroll_handler = self.thumbscroll.get_vscrollbar().connect("value-changed", self.thumbpane_scrolled)
  664. # Since GNOME does its own thing for the toolbar style...
  665. # Requires gnome-python installed to work (but optional)
  666. try:
  667. client = gconf.client_get_default()
  668. style = client.get_string('/desktop/gnome/interface/toolbar_style')
  669. if style == "both":
  670. self.toolbar.set_style(gtk.TOOLBAR_BOTH)
  671. elif style == "both-horiz":
  672. self.toolbar.set_style(gtk.TOOLBAR_BOTH_HORIZ)
  673. elif style == "icons":
  674. self.toolbar.set_style(gtk.TOOLBAR_ICONS)
  675. elif style == "text":
  676. self.toolbar.set_style(gtk.TOOLBAR_TEXT)
  677. client.add_dir("/desktop/gnome/interface", gconf.CLIENT_PRELOAD_NONE)
  678. client.notify_add("/desktop/gnome/interface/toolbar_style", self.gconf_key_changed)
  679. except:
  680. pass
  681. # Show GUI:
  682. if not self.toolbar_show:
  683. self.toolbar.set_property('visible', False)
  684. self.toolbar.set_no_show_all(True)
  685. if not self.statusbar_show:
  686. self.statusbar.set_property('visible', False)
  687. self.statusbar.set_no_show_all(True)
  688. self.statusbar2.set_property('visible', False)
  689. self.statusbar2.set_no_show_all(True)
  690. if not self.thumbpane_show:
  691. self.thumbscroll.set_property('visible', False)
  692. self.thumbscroll.set_no_show_all(True)
  693. self.hscroll.set_no_show_all(True)
  694. self.vscroll.set_no_show_all(True)
  695. go_into_fullscreen = False
  696. if opts != []:
  697. for o, a in opts:
  698. if (o in ("-f", "--fullscreen")) or ((o in ("-s", "--slideshow")) and self.slideshow_in_fullscreen):
  699. go_into_fullscreen = True
  700. if go_into_fullscreen or self.start_in_fullscreen:
  701. self.enter_fullscreen(None)
  702. self.statusbar.set_no_show_all(True)
  703. self.statusbar2.set_no_show_all(True)
  704. self.toolbar.set_no_show_all(True)
  705. self.menubar.set_no_show_all(True)
  706. self.thumbscroll.set_no_show_all(True)
  707. self.window.show_all()
  708. self.ss_exit.set_size_request(self.ss_start.size_request()[0], self.ss_stop.size_request()[1])
  709. self.ss_randomize.set_size_request(self.ss_start.size_request()[0], -1)
  710. self.ss_start.set_size_request(self.ss_start.size_request()[0]*2, -1)
  711. self.ss_stop.set_size_request(self.ss_stop.size_request()[0]*2, -1)
  712. self.UIManager.get_widget('/Popup/Exit Full Screen').hide()
  713. self.layout.set_flags(gtk.CAN_FOCUS)
  714. self.window.set_focus(self.layout)
  715. #sets the visibility of some menu entries
  716. self.set_slideshow_sensitivities()
  717. self.UIManager.get_widget('/MainMenu/MiscKeysMenuHidden').set_property('visible', False)
  718. if opts != []:
  719. for o, a in opts:
  720. if o in ("-f", "--fullscreen"):
  721. self.UIManager.get_widget('/Popup/Exit Full Screen').show()
  722. # If arguments (filenames) were passed, try to open them:
  723. self.image_list = []
  724. if args != []:
  725. for i in range(len(args)):
  726. args[i] = urllib.url2pathname(args[i])
  727. self.expand_filelist_and_load_image(args)
  728. else:
  729. self.set_go_sensitivities(False)
  730. self.set_image_sensitivities(False)
  731. if opts != []:
  732. for o, a in opts:
  733. if o in ("-s", "--slideshow"):
  734. self.toggle_slideshow(None)
  735. def refresh_recent_files_menu(self):
  736. if self.merge_id_recent:
  737. self.UIManager.remove_ui(self.merge_id_recent)
  738. if self.actionGroupRecent:
  739. self.UIManager.remove_action_group(self.actionGroupRecent)
  740. self.actionGroupRecent = None
  741. self.actionGroupRecent = gtk.ActionGroup('RecentFiles')
  742. self.UIManager.ensure_update()
  743. for i in range(len(self.recentfiles)):
  744. if len(self.recentfiles[i]) > 0:
  745. filename = self.recentfiles[i].split("/")[-1]
  746. if len(filename) > 0:
  747. if len(filename) > 27:
  748. # Replace end of file name (excluding extension) with ..
  749. try:
  750. menu_name = filename[:25] + '..' + os.path.splitext(filename)[1]
  751. except:
  752. menu_name = filename[0]
  753. else:
  754. menu_name = filename
  755. menu_name = menu_name.replace('_','__')
  756. action = [(str(i), None, menu_name, '<Alt>' + str(i+1), None, self.recent_action_click)]
  757. self.actionGroupRecent.add_actions(action)
  758. uiDescription = """
  759. <ui>
  760. <menubar name="MainMenu">
  761. <menu action="FileMenu">
  762. <placeholder name="Recent Files">
  763. """
  764. for i in range(len(self.recentfiles)):
  765. if len(self.recentfiles[i]) > 0:
  766. uiDescription = uiDescription + """<menuitem action=\"""" + str(i) + """\"/>"""
  767. uiDescription = uiDescription + """</placeholder></menu></menubar></ui>"""
  768. self.merge_id_recent = self.UIManager.add_ui_from_string(uiDescription)
  769. self.UIManager.insert_action_group(self.actionGroupRecent, 0)
  770. self.UIManager.get_widget('/MainMenu/MiscKeysMenuHidden').set_property('visible', False)
  771. def refresh_custom_actions_menu(self):
  772. if self.merge_id:
  773. self.UIManager.remove_ui(self.merge_id)
  774. if self.actionGroupCustom:
  775. self.UIManager.remove_action_group(self.actionGroupCustom)
  776. self.actionGroupCustom = None
  777. self.actionGroupCustom = gtk.ActionGroup('CustomActions')
  778. self.UIManager.ensure_update()
  779. for i in range(len(self.action_names)):
  780. action = [(self.action_names[i], None, self.action_names[i], self.action_shortcuts[i], None, self.custom_action_click)]
  781. self.actionGroupCustom.add_actions(action)
  782. uiDescription = """
  783. <ui>
  784. <menubar name="MainMenu">
  785. <menu action="EditMenu">
  786. <menu action="ActionSubMenu">
  787. """
  788. for i in range(len(self.action_names)):
  789. uiDescription = uiDescription + """<menuitem action=\"""" + self.action_names[len(self.action_names)-i-1].replace('&','&amp;') + """\" position="top"/>"""
  790. uiDescription = uiDescription + """</menu></menu></menubar></ui>"""
  791. self.merge_id = self.UIManager.add_ui_from_string(uiDescription)
  792. self.UIManager.insert_action_group(self.actionGroupCustom, 0)
  793. self.UIManager.get_widget('/MainMenu/MiscKeysMenuHidden').set_property('visible', False)
  794. def thumbpane_update_images(self, clear_first=False, force_upto_imgnum=-1):
  795. self.stop_now = False
  796. # When first populating the thumbpane, make sure we go up to at least
  797. # force_upto_imgnum so that we can show this image selected:
  798. if clear_first:
  799. self.thumbpane_clear_list()
  800. # Load all images up to the bottom ofo the visible thumbpane rect:
  801. rect = self.thumbpane.get_visible_rect()
  802. bottom_coord = rect.y + rect.height + self.thumbnail_size
  803. if bottom_coord > self.thumbpane_bottom_coord_loaded:
  804. self.thumbpane_bottom_coord_loaded = bottom_coord
  805. # update images:
  806. if not self.thumbpane_updating:
  807. thread = threading.Thread(target=self.thumbpane_update_pending_images, args=(force_upto_imgnum, None))
  808. thread.setDaemon(True)
  809. thread.start()
  810. def thumbpane_create_dir(self):
  811. if not os.path.exists(os.path.expanduser('~/.thumbnails/')):
  812. os.mkdir(os.path.expanduser('~/.thumbnails/'))
  813. if not os.path.exists(os.path.expanduser('~/.thumbnails/normal/')):
  814. os.mkdir(os.path.expanduser('~/.thumbnails/normal/'))
  815. def thumbpane_update_pending_images(self, force_upto_imgnum, foo):
  816. self.thumbpane_updating = True
  817. self.thumbpane_create_dir()
  818. # Check to see if any images need their thumbnails generated.
  819. curr_coord = 0
  820. imgnum = 0
  821. while curr_coord < self.thumbpane_bottom_coord_loaded or imgnum <= force_upto_imgnum:
  822. if self.closing_app or self.stop_now or not self.thumbpane_show:
  823. break
  824. if imgnum >= len(self.image_list):
  825. break
  826. self.thumbpane_set_image(self.image_list[imgnum], imgnum)
  827. curr_coord += self.thumbpane.get_background_area((imgnum,),self.thumbcolumn).height
  828. if force_upto_imgnum == imgnum:
  829. # Verify that the user hasn't switched images while we're loading thumbnails:
  830. if force_upto_imgnum == self.curr_img_in_list:
  831. gobject.idle_add(self.thumbpane_select, force_upto_imgnum)
  832. imgnum += 1
  833. self.thumbpane_updating = False
  834. def thumbpane_clear_list(self):
  835. self.thumbpane_bottom_coord_loaded = 0
  836. self.thumbscroll.get_vscrollbar().handler_block(self.thumb_scroll_handler)
  837. self.thumblist.clear()
  838. self.thumbscroll.get_vscrollbar().handler_unblock(self.thumb_scroll_handler)
  839. for image in self.image_list:
  840. blank_pix = self.get_blank_pix_for_image(image)
  841. self.thumblist.append([blank_pix])
  842. self.thumbnail_loaded = [False]*len(self.image_list)
  843. def thumbpane_set_image(self, image_name, imgnum, force_update=False):
  844. if self.thumbpane_show:
  845. if not self.thumbnail_loaded[imgnum] or force_update:
  846. filename, thumbfile = self.thumbnail_get_name(image_name)
  847. pix = self.thumbpane_get_pixbuf(thumbfile, filename, force_update)
  848. if pix:
  849. if self.thumbnail_size != 128:
  850. # 128 is the size of the saved thumbnail, so convert if different:
  851. pix, image_width, image_height = self.get_pixbuf_of_size(pix, self.thumbnail_size, gtk.gdk.INTERP_TILES)
  852. self.thumbnail_loaded[imgnum] = True
  853. self.thumbscroll.get_vscrollbar().handler_block(self.thumb_scroll_handler)
  854. pix = self.pixbuf_add_border(pix)
  855. try:
  856. self.thumblist[imgnum] = [pix]
  857. except:
  858. pass
  859. self.thumbscroll.get_vscrollbar().handler_unblock(self.thumb_scroll_handler)
  860. def thumbnail_get_name(self, image_name):
  861. filename = os.path.expanduser('file://' + image_name)
  862. uriname = os.path.expanduser('file://' + urllib.pathname2url(image_name))
  863. if HAS_HASHLIB:
  864. m = hashlib.md5()
  865. else:
  866. m = md5.new()
  867. m.update(uriname)
  868. mhex = m.hexdigest()
  869. mhex_filename = os.path.expanduser('~/.thumbnails/normal/' + mhex + '.png')
  870. return filename, mhex_filename
  871. def thumbpane_get_pixbuf(self, thumb_url, image_url, force_generation):
  872. # Returns a valid pixbuf or None if a pixbuf cannot be generated. Tries to re-use
  873. # a thumbnail from ~/.thumbails/normal/, otherwise generates one with the
  874. # XDG filename: md5(file:///full/path/to/image).png
  875. imgfile = image_url
  876. if imgfile[:7] == 'file://':
  877. imgfile = imgfile[7:]
  878. try:
  879. if os.path.exists(thumb_url) and not force_generation:
  880. pix = gtk.gdk.pixbuf_new_from_file(thumb_url)
  881. pix_mtime = pix.get_option('tEXt::Thumb::MTime')
  882. if pix_mtime:
  883. st = os.stat(imgfile)
  884. file_mtime = str(st[stat.ST_MTIME])
  885. # If the mtimes match, we're good. if not, regenerate the thumbnail..
  886. if pix_mtime == file_mtime:
  887. return pix
  888. # Create the 128x128 thumbnail:
  889. uri = 'file://' + urllib.pathname2url(imgfile)
  890. pix = gtk.gdk.pixbuf_new_from_file(imgfile)
  891. pix, image_width, image_height = self.get_pixbuf_of_size(pix, 128, gtk.gdk.INTERP_TILES)
  892. st = os.stat(imgfile)
  893. file_mtime = str(st[stat.ST_MTIME])
  894. # Save image to .thumbnails:
  895. pix.save(thumb_url, "png", {'tEXt::Thumb::URI':uri, 'tEXt::Thumb::MTime':file_mtime, 'tEXt::Software':'Mirage' + __version__})
  896. return pix
  897. except:
  898. return None
  899. def thumbpane_load_image(self, treeview, imgnum):
  900. if imgnum != self.curr_img_in_list:
  901. gobject.idle_add(self.goto_image, str(imgnum), None)
  902. def thumbpane_selection_changed(self, treeview):
  903. cancel = self.autosave_image()
  904. if cancel:
  905. # Revert selection...
  906. gobject.idle_add(self.thumbpane_select, self.curr_img_in_list)
  907. return True
  908. try:
  909. model, paths = self.thumbpane.get_selection().get_selected_rows()
  910. imgnum = paths[0][0]
  911. if not self.thumbnail_loaded[imgnum]:
  912. self.thumbpane_set_image(self.image_list[imgnum], imgnum)
  913. gobject.idle_add(self.thumbpane_load_image, treeview, imgnum)
  914. except:
  915. pass
  916. def thumbpane_select(self, imgnum):
  917. if self.thumbpane_show:
  918. self.thumbpane.get_selection().handler_block(self.thumb_sel_handler)
  919. try:
  920. self.thumbpane.get_selection().select_path((imgnum,))
  921. self.thumbpane.scroll_to_cell((imgnum,))
  922. except:
  923. pass
  924. self.thumbpane.get_selection().handler_unblock(self.thumb_sel_handler)
  925. def thumbpane_set_size(self):
  926. self.thumbcolumn.set_fixed_width(self.thumbpane_get_size())
  927. self.window_resized(None, self.window.allocation, True)
  928. def thumbpane_get_size(self):
  929. return int(self.thumbnail_size * 1.3)
  930. def thumbpane_scrolled(self, range):
  931. self.thumbpane_update_images()
  932. def get_blank_pix_for_image(self, image):
  933. # Sizes the "blank image" icon for the thumbpane. This will ensure that we don't
  934. # load a humongous icon for a small pix, for example, and will keep the thumbnails
  935. # from shifting around when they are actually loaded.
  936. try:
  937. info = gtk.gdk.pixbuf_get_file_info(image)
  938. imgwidth = float(info[1])
  939. imgheight = float(info[2])
  940. if imgheight > self.thumbnail_size:
  941. if imgheight > imgwidth:
  942. imgheight = self.thumbnail_size
  943. else:
  944. imgheight = imgheight/imgwidth * self.thumbnail_size
  945. imgheight = 2 + int(imgheight) # Account for border that will be added to thumbnails..
  946. imgwidth = self.thumbnail_size
  947. except:
  948. imgheight = 2 + self.thumbnail_size
  949. imgwidth = self.thumbnail_size
  950. blank_pix = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, imgwidth, imgheight)
  951. blank_pix.fill(0x00000000)
  952. imgwidth2 = int(imgheight*0.8)
  953. imgheight2 = int(imgheight*0.8)
  954. composite_pix = self.blank_image.scale_simple(imgwidth2, imgheight2, gtk.gdk.INTERP_BILINEAR)
  955. leftcoord = int((imgwidth - imgwidth2)/2)
  956. topcoord = int((imgheight - imgheight2)/2)
  957. composite_pix.copy_area(0, 0, imgwidth2, imgheight2, blank_pix, leftcoord, topcoord)
  958. return blank_pix
  959. def find_path(self, filename, exit_on_fail=True):
  960. """ Find a pixmap or icon by looking through standard dirs.
  961. If the image isn't found exit with error status 1 unless
  962. exit_on_fail is set to False, then return None """
  963. if not self.resource_path_list:
  964. #If executed from mirage in bin this points to the basedir
  965. basedir_mirage = os.path.split(sys.path[0])[0]
  966. #If executed from mirage.py module in python lib this points to the basedir
  967. f0 = os.path.split(__file__)[0].split('/lib')[0]
  968. self.resource_path_list = list(set(filter(os.path.isdir, [
  969. os.path.join(basedir_mirage, 'share', 'mirage'),
  970. os.path.join(basedir_mirage, 'share', 'pixmaps'),
  971. os.path.join(sys.prefix, 'share', 'mirage'),
  972. os.path.join(sys.prefix, 'share', 'pixmaps'),
  973. os.path.join(sys.prefix, 'local', 'share', 'mirage'),
  974. os.path.join(sys.prefix, 'local', 'share', 'pixmaps'),
  975. sys.path[0], #If it's run non-installed
  976. os.path.join(f0, 'share', 'mirage'),
  977. os.path.join(f0, 'share', 'pixmaps'),
  978. ])))
  979. for path in self.resource_path_list:
  980. pix = os.path.join(path, filename)
  981. if os.path.exists(pix):
  982. return pix
  983. # If we reached here, we didn't find the pixmap
  984. if exit_on_fail:
  985. print _("Couldn't find the image %s. Please check your installation.") % filename
  986. sys.exit(1)
  987. else:
  988. return None
  989. def gconf_key_changed(self, client, cnxn_id, entry, label):
  990. if entry.value.type == gconf.VALUE_STRING:
  991. style = entry.value.to_string()
  992. if style == "both":
  993. self.toolbar.set_style(gtk.TOOLBAR_BOTH)
  994. elif style == "both-horiz":
  995. self.toolbar.set_style(gtk.TOOLBAR_BOTH_HORIZ)
  996. elif style == "icons":
  997. self.toolbar.set_style(gtk.TOOLBAR_ICONS)
  998. elif style == "text":
  999. self.toolbar.set_style(gtk.TOOLBAR_TEXT)
  1000. if self.image_loaded and self.last_image_action_was_fit:
  1001. if self.last_image_action_was_smart_fit:
  1002. self.zoom_to_fit_or_1_to_1(None, False, False)
  1003. else:
  1004. self.zoom_to_fit_window(None, False, False)
  1005. def toolbar_focused(self, widget, direction):
  1006. self.layout.grab_focus()
  1007. return True
  1008. def topwindow_keypress(self, widget, event):
  1009. # For whatever reason, 'Left' and 'Right' cannot be used as menu
  1010. # accelerators so we will manually check for them here:
  1011. if (not (event.state & gtk.gdk.SHIFT_MASK)) and not (event.state & gtk.gdk.CONTROL_MASK) and not (event.state & gtk.gdk.MOD1_MASK) and not (event.state & gtk.gdk.MOD2_MASK) and not (event.state & gtk.gdk.CONTROL_MASK):
  1012. if event.keyval == gtk.gdk.keyval_from_name('Left') or event.keyval == gtk.gdk.keyval_from_name('Up'):
  1013. self.goto_prev_image(None)
  1014. return
  1015. elif event.keyval == gtk.gdk.keyval_from_name('Right') or event.keyval == gtk.gdk.keyval_from_name('Down'):
  1016. self.goto_next_image(None)
  1017. return
  1018. shortcut = gtk.accelerator_name(event.keyval, event.state)
  1019. if "Escape" in shortcut:
  1020. self.stop_now = True
  1021. self.searching_for_images = False
  1022. while gtk.events_pending():
  1023. gtk.main_iteration()
  1024. self.update_title()
  1025. return
  1026. def parse_action_command(self, command, batchmode):
  1027. self.running_custom_actions = True
  1028. self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
  1029. while gtk.events_pending():
  1030. gtk.main_iteration()
  1031. self.curr_custom_action = 0
  1032. if batchmode:
  1033. self.num_custom_actions = len(self.image_list)
  1034. for i in range(self.num_custom_actions):
  1035. self.curr_custom_action += 1
  1036. self.update_statusbar()
  1037. while gtk.events_pending():
  1038. gtk.main_iteration()
  1039. imagename = self.image_list[i]
  1040. self.parse_action_command2(command, imagename)
  1041. else:
  1042. self.num_custom_actions = 1
  1043. self.curr_custom_action = 1
  1044. self.update_statusbar()
  1045. while gtk.events_pending():
  1046. gtk.main_iteration()
  1047. self.parse_action_command2(command, self.currimg_name)
  1048. gc.collect()
  1049. self.change_cursor(None)
  1050. # Refresh the current image or any preloaded needed if they have changed:
  1051. if not os.path.exists(self.currimg_name):
  1052. self.currimg_pixbuf_original = None
  1053. self.image_load_failed(False)
  1054. else:
  1055. animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
  1056. if animtest.is_static_image():
  1057. if self.images_are_different(animtest.get_static_image(), self.currimg_pixbuf_original):
  1058. self.load_new_image2(False, False, True, False)
  1059. else:
  1060. if self.images_are_different(animtest, self.currimg_pixbuf_original):
  1061. self.load_new_image2(False, False, True, False)
  1062. self.running_custom_actions = False
  1063. self.update_statusbar()
  1064. while gtk.events_pending():
  1065. gtk.main_iteration()
  1066. if not os.path.exists(self.preloadimg_prev_name):
  1067. self.preloadimg_prev_in_list = -1
  1068. else:
  1069. animtest = gtk.gdk.PixbufAnimation(self.preloadimg_prev_name)
  1070. if animtest.is_static_image():
  1071. if self.images_are_different(animtest.get_static_image(), self.preloadimg_prev_pixbuf_original):
  1072. self.preloadimg_prev_in_list = -1
  1073. self.preload_when_idle = gobject.idle_add(self.preload_prev_image, False)
  1074. else:
  1075. if self.images_are_different(animtest, self.preloadimg_prev_pixbuf_original):
  1076. self.preloadimg_prev_in_list = -1
  1077. self.preload_when_idle = gobject.idle_add(self.preload_prev_image, False)
  1078. if not os.path.exists(self.preloadimg_next_name):
  1079. self.preloadimg_next_in_list = -1
  1080. else:
  1081. animtest = gtk.gdk.PixbufAnimation(self.preloadimg_next_name)
  1082. if animtest.is_static_image():
  1083. if self.images_are_different(animtest.get_static_image(), self.preloadimg_next_pixbuf_original):
  1084. self.preloadimg_next_in_list = -1
  1085. self.preload_when_idle = gobject.idle_add(self.preload_next_image, False)
  1086. else:
  1087. if self.images_are_different(animtest, self.preloadimg_next_pixbuf_original):
  1088. self.preloadimg_next_in_list = -1
  1089. self.preload_when_idle = gobject.idle_add(self.preload_next_image, False)
  1090. self.stop_now = False
  1091. if batchmode:
  1092. # Update all thumbnails:
  1093. gobject.idle_add(self.thumbpane_update_images, True, self.curr_img_in_list)
  1094. else:
  1095. # Update only the current thumbnail:
  1096. gobject.idle_add(self.thumbpane_set_image, self.image_list[self.curr_img_in_list], self.curr_img_in_list, True)
  1097. def images_are_different(self, pixbuf1, pixbuf2):
  1098. if pixbuf1.get_pixels() == pixbuf2.get_pixels():
  1099. return False
  1100. else:
  1101. return True
  1102. def recent_action_click(self, action):
  1103. self.stop_now = True
  1104. while gtk.events_pending():
  1105. gtk.main_iteration()
  1106. cancel = self.autosave_image()
  1107. if cancel:
  1108. return
  1109. index = int(action.get_name())
  1110. if os.path.isfile(self.recentfiles[index]) or os.path.exists(self.recentfiles[index]) or self.recentfiles[index].startswith('http://') or self.recentfiles[index].startswith('ftp://'):
  1111. self.expand_filelist_and_load_image([self.recentfiles[index]])
  1112. else:
  1113. self.image_list = []
  1114. self.curr_img_in_list = 0
  1115. self.image_list.append(self.recentfiles[index])
  1116. self.image_load_failed(False)
  1117. self.recent_file_remove_and_refresh(index)
  1118. def recent_file_remove_and_refresh_name(self, rmfile):
  1119. index_num = 0
  1120. for imgfile in self.recentfiles:
  1121. if imgfile == rmfile:
  1122. self.recent_file_remove_and_refresh(index_num)
  1123. break
  1124. index_num += index_num
  1125. def recent_file_remove_and_refresh(self, index_num):
  1126. i = index_num
  1127. while i < len(self.recentfiles)-1:
  1128. self.recentfiles[i] = self.recentfiles[i+1]
  1129. i = i + 1
  1130. # Set last item empty:
  1131. self.recentfiles[len(self.recentfiles)-1] = ''
  1132. self.refresh_recent_files_menu()
  1133. def recent_file_add_and_refresh(self, addfile):
  1134. # First check if the filename is already in the list:
  1135. for i in range(len(self.recentfiles)):
  1136. if len(self.recentfiles[i]) > 0:
  1137. if addfile == self.recentfiles[i]:
  1138. # If found in list, put to position 1 and decrement the rest:
  1139. j = i
  1140. while j > 0:
  1141. self.recentfiles[j] = self.recentfiles[j-1]
  1142. j = j - 1
  1143. self.recentfiles[0] = addfile
  1144. self.refresh_recent_files_menu()
  1145. return
  1146. # If not found, put to position 1, decrement the rest:
  1147. j = len(self.recentfiles)-1
  1148. while j > 0:
  1149. self.recentfiles[j] = self.recentfiles[j-1]
  1150. j = j - 1
  1151. if len(self.recentfiles) > 0:
  1152. self.recentfiles[0] = addfile
  1153. self.refresh_recent_files_menu()
  1154. def custom_action_click(self, action):
  1155. if self.UIManager.get_widget('/MainMenu/EditMenu/ActionSubMenu/' + action.get_name()).get_property('sensitive'):
  1156. for i in range(len(self.action_shortcuts)):
  1157. try:
  1158. if action.get_name() == self.action_names[i]:
  1159. self.parse_action_command(self.action_commands[i], self.action_batch[i])
  1160. except:
  1161. pass
  1162. def parse_action_command2(self, cmd, imagename):
  1163. # Executes the given command using ``os.system``, substituting "%"-macros approprately.
  1164. def sh_esc(s):
  1165. import re
  1166. return re.sub(r'[^/._a-zA-Z0-9-]', lambda c: '\\'+c.group(), s)
  1167. cmd = cmd.strip()
  1168. # [NEXT] and [PREV] are only valid alone or at the end of the command
  1169. if cmd == "[NEXT]":
  1170. self.goto_next_image(None)
  1171. return
  1172. elif cmd == "[PREV]":
  1173. self.goto_prev_image(None)
  1174. return
  1175. # -1=go to previous, 1=go to next, 0=don't change
  1176. prev_or_next=0
  1177. if cmd[-6:] == "[NEXT]":
  1178. prev_or_next=1
  1179. cmd = cmd[:-6]
  1180. elif cmd[-6:] == "[PREV]":
  1181. prev_or_next=-1
  1182. cmd = cmd[:-6]
  1183. if "%F" in cmd:
  1184. cmd = cmd.replace("%F", sh_esc(imagename))
  1185. if "%N" in cmd:
  1186. cmd = cmd.replace("%N", sh_esc(os.path.splitext(os.path.basename(imagename))[0]))
  1187. if "%P" in cmd:
  1188. cmd = cmd.replace("%P", sh_esc(os.path.dirname(imagename) + "/"))
  1189. if "%E" in cmd:
  1190. cmd = cmd.replace("%E", sh_esc(os.path.splitext(os.path.basename(imagename))[1]))
  1191. if "%L" in cmd:
  1192. cmd = cmd.replace("%L", " ".join([sh_esc(s) for s in self.image_list]))
  1193. if self.verbose:
  1194. print _("Action: %s") % cmd
  1195. shell_rc = os.system(cmd) >> 8
  1196. if self.verbose:
  1197. print _("Action return code: %s") % shell_rc
  1198. if shell_rc != 0:
  1199. msg = _('Unable to launch \"%s\". Please specify a valid command from Edit > Custom Actions.') % cmd
  1200. error_dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, msg)
  1201. error_dialog.set_title(_("Invalid Custom Action"))
  1202. error_dialog.run()
  1203. error_dialog.destroy()
  1204. elif prev_or_next == 1:
  1205. self.goto_next_image(None)
  1206. elif prev_or_next == -1:
  1207. self.goto_prev_image(None)
  1208. self.running_custom_actions = False
  1209. def set_go_sensitivities(self, enable):
  1210. self.UIManager.get_widget('/MainMenu/GoMenu/Previous Image').set_sensitive(enable)
  1211. self.UIManager.get_widget('/MainMenu/GoMenu/Next Image').set_sensitive(enable)
  1212. self.UIManager.get_widget('/MainMenu/GoMenu/Random Image').set_sensitive(enable)
  1213. self.UIManager.get_widget('/MainMenu/GoMenu/First Image').set_sensitive(enable)
  1214. self.UIManager.get_widget('/MainMenu/GoMenu/Last Image').set_sensitive(enable)
  1215. self.UIManager.get_widget('/Popup/Previous Image').set_sensitive(enable)
  1216. self.UIManager.get_widget('/Popup/Next Image').set_sensitive(enable)
  1217. self.UIManager.get_widget('/MainToolbar/Previous2').set_sensitive(enable)
  1218. self.UIManager.get_widget('/MainToolbar/Next2').set_sensitive(enable)
  1219. self.ss_forward.set_sensitive(enable)
  1220. self.ss_back.set_sensitive(enable)
  1221. def set_image_sensitivities(self, enable):
  1222. self.set_zoom_in_sensitivities(enable)
  1223. self.set_zoom_out_sensitivities(enable)
  1224. self.UIManager.get_widget('/MainMenu/ViewMenu/1:1').set_sensitive(enable)
  1225. self.UIManager.get_widget('/MainMenu/ViewMenu/Fit').set_sensitive(enable)
  1226. self.UIManager.get_widget('/MainMenu/EditMenu/Delete Image').set_sensitive(enable)
  1227. self.UIManager.get_widget('/MainMenu/EditMenu/Rename Image').set_sensitive(enable)
  1228. self.UIManager.get_widget('/MainMenu/EditMenu/Crop').set_sensitive(enable)
  1229. self.UIManager.get_widget('/MainMenu/EditMenu/Resize').set_sensitive(enable)
  1230. self.UIManager.get_widget('/MainMenu/EditMenu/Saturation').set_sensitive(enable)
  1231. self.UIManager.get_widget('/MainToolbar/1:1').set_sensitive(enable)
  1232. self.UIManager.get_widget('/MainToolbar/Fit').set_sensitive(enable)
  1233. self.UIManager.get_widget('/Popup/1:1').set_sensitive(enable)
  1234. self.UIManager.get_widget('/Popup/Fit').set_sensitive(enable)
  1235. self.UIManager.get_widget('/MainMenu/FileMenu/Save As').set_sensitive(enable)
  1236. self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_sensitive(False)
  1237. self.UIManager.get_widget('/MainMenu/FileMenu/Properties').set_sensitive(False)
  1238. # Only jpeg, png, and bmp images are currently supported for saving
  1239. if len(self.image_list) > 0:
  1240. try:
  1241. filetype = gtk.gdk.pixbuf_get_file_info(self.currimg_name)[0]['name']
  1242. self.UIManager.get_widget('/MainMenu/FileMenu/Properties').set_sensitive(True)
  1243. if self.filetype_is_writable(filetype):
  1244. self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_sensitive(enable)
  1245. except:
  1246. self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_sensitive(False)
  1247. if self.actionGroupCustom:
  1248. for action in self.action_names:
  1249. self.UIManager.get_widget('/MainMenu/EditMenu/ActionSubMenu/' + action).set_sensitive(enable)
  1250. if not HAS_IMGFUNCS:
  1251. enable = False
  1252. self.UIManager.get_widget('/MainMenu/EditMenu/Rotate Left').set_sensitive(enable)
  1253. self.UIManager.get_widget('/MainMenu/EditMenu/Rotate Right').set_sensitive(enable)
  1254. self.UIManager.get_widget('/MainMenu/EditMenu/Flip Vertically').set_sensitive(enable)
  1255. self.UIManager.get_widget('/MainMenu/EditMenu/Flip Horizontally').set_sensitive(enable)
  1256. def set_zoom_in_sensitivities(self, enable):
  1257. self.UIManager.get_widget('/MainMenu/ViewMenu/In').set_sensitive(enable)
  1258. self.UIManager.get_widget('/MainToolbar/In').set_sensitive(enable)
  1259. self.UIManager.get_widget('/Popup/In').set_sensitive(enable)
  1260. def set_zoom_out_sensitivities(self, enable):
  1261. self.UIManager.get_widget('/MainMenu/ViewMenu/Out').set_sensitive(enable)
  1262. self.UIManager.get_widget('/MainToolbar/Out').set_sensitive(enable)
  1263. self.UIManager.get_widget('/Popup/Out').set_sensitive(enable)
  1264. def set_next_image_sensitivities(self, enable):
  1265. self.UIManager.get_widget('/MainToolbar/Next2').set_sensitive(enable)
  1266. self.UIManager.get_widget('/MainMenu/GoMenu/Next Image').set_sensitive(enable)
  1267. self.UIManager.get_widget('/Popup/Next Image').set_sensitive(enable)
  1268. self.ss_forward.set_sensitive(enable)
  1269. def set_previous_image_sensitivities(self, enable):
  1270. self.UIManager.get_widget('/MainToolbar/Previous2').set_sensitive(enable)
  1271. self.UIManager.get_widget('/MainMenu/GoMenu/Previous Image').set_sensitive(enable)
  1272. self.UIManager.get_widget('/Popup/Previous Image').set_sensitive(enable)
  1273. self.ss_back.set_sensitive(enable)
  1274. def set_first_image_sensitivities(self, enable):
  1275. self.UIManager.get_widget('/MainMenu/GoMenu/First Image').set_sensitive(enable)
  1276. def set_last_image_sensitivities(self, enable):
  1277. self.UIManager.get_widget('/MainMenu/GoMenu/Last Image').set_sensitive(enable)
  1278. def set_random_image_sensitivities(self, enable):
  1279. self.UIManager.get_widget('/MainMenu/GoMenu/Random Image').set_sensitive(enable)
  1280. def set_slideshow_sensitivities(self):
  1281. if len(self.image_list) <=1:
  1282. self.UIManager.get_widget('/MainMenu/GoMenu/Start Slideshow').show()
  1283. self.UIManager.get_widget('/MainMenu/GoMenu/Start Slideshow').set_sensitive(False)
  1284. self.UIManager.get_widget('/MainMenu/GoMenu/Stop Slideshow').hide()
  1285. self.UIManager.get_widget('/MainMenu/GoMenu/Stop Slideshow').set_sensitive(False)
  1286. elif self.slideshow_mode:
  1287. self.UIManager.get_widget('/MainMenu/GoMenu/Start Slideshow').hide()
  1288. self.UIManager.get_widget('/MainMenu/GoMenu/Start Slideshow').set_sensitive(False)
  1289. self.UIManager.get_widget('/MainMenu/GoMenu/Stop Slideshow').show()
  1290. self.UIManager.get_widget('/MainMenu/GoMenu/Stop Slideshow').set_sensitive(True)
  1291. else:
  1292. self.UIManager.get_widget('/MainMenu/GoMenu/Start Slideshow').show()
  1293. self.UIManager.get_widget('/MainMenu/GoMenu/Start Slideshow').set_sensitive(True)
  1294. self.UIManager.get_widget('/MainMenu/GoMenu/Stop Slideshow').hide()
  1295. self.UIManager.get_widget('/MainMenu/GoMenu/Stop Slideshow').set_sensitive(False)
  1296. if self.slideshow_mode:
  1297. self.UIManager.get_widget('/Popup/Start Slideshow').hide()
  1298. self.UIManager.get_widget('/Popup/Stop Slideshow').show()
  1299. else:
  1300. self.UIManager.get_widget('/Popup/Start Slideshow').show()
  1301. self.UIManager.get_widget('/Popup/Stop Slideshow').hide()
  1302. if len(self.image_list) <=1:
  1303. self.UIManager.get_widget('/Popup/Start Slideshow').set_sensitive(False)
  1304. else:
  1305. self.UIManager.get_widget('/Popup/Start Slideshow').set_sensitive(True)
  1306. def set_zoom_sensitivities(self):
  1307. if not self.currimg_is_animation:
  1308. self.set_zoom_out_sensitivities(True)
  1309. self.set_zoom_in_sensitivities(True)
  1310. else:
  1311. self.set_zoom_out_sensitivities(False)
  1312. self.set_zoom_in_sensitivities(False)
  1313. def print_version(self):
  1314. print _("Version: Mirage"), __version__
  1315. print _("Website: http://mirageiv.berlios.de")
  1316. def print_usage(self):
  1317. self.print_version()
  1318. print ""
  1319. print _("Usage: mirage [OPTION]... FILES|FOLDERS...")
  1320. print ""
  1321. print _("Options") + ":"
  1322. print " -h, --help " + _("Show this help and exit")
  1323. print " -v, --version " + _("Show version information and exit")
  1324. print " -V, --verbose " + _("Show more detailed information")
  1325. print " -R, --recursive " + _("Recursively include all images found in")
  1326. print " " + _("subdirectories of FOLDERS")
  1327. print " -s, --slideshow " + _("Start in slideshow mode")
  1328. print " -f, --fullscreen " + _("Start in fullscreen mode")
  1329. print " -o, --onload 'cmd' " + _("Execute 'cmd' when an image is loaded")
  1330. print " " + _("uses same syntax as custom actions,\n")
  1331. print " " + _("i.e. mirage -o 'echo file is %F'")
  1332. def delay_changed(self, action):
  1333. self.curr_slideshow_delay = self.ss_delayspin.get_value()
  1334. if self.slideshow_mode:
  1335. gobject.source_remove(self.timer_delay)
  1336. if self.curr_slideshow_random:
  1337. self.timer_delay = gobject.timeout_add(int(self.curr_slideshow_delay*1000), self.goto_random_image, "ss")
  1338. else:
  1339. self.timer_delay = gobject.timeout_add((self.curr_slideshow_delay*1000), self.goto_next_image, "ss")
  1340. self.window.set_focus(self.layout)
  1341. def random_changed(self, action):
  1342. self.curr_slideshow_random = self.ss_randomize.get_active()
  1343. def motion_cb(self, widget, context, x, y, time):
  1344. context.drag_status(gtk.gdk.ACTION_COPY, time)
  1345. return True
  1346. def drop_cb(self, widget, context, x, y, selection, info, time):
  1347. uri = selection.data.strip()
  1348. path = urllib.url2pathname(uri)
  1349. paths = path.rsplit('\n')
  1350. for i, path in enumerate(paths):
  1351. paths[i] = path.rstrip('\r')
  1352. self.expand_filelist_and_load_image(paths)
  1353. def put_error_image_to_window(self):
  1354. self.imageview.set_from_stock(gtk.STOCK_MISSING_IMAGE, gtk.ICON_SIZE_LARGE_TOOLBAR)
  1355. self.currimg_width = self.imageview.size_request()[0]
  1356. self.currimg_height = self.imageview.size_request()[1]
  1357. self.center_image()
  1358. self.set_go_sensitivities(False)
  1359. self.set_image_sensitivities(False)
  1360. self.update_statusbar()
  1361. self.loaded_img_in_list = -1
  1362. return
  1363. def expose_event(self, widget, event):
  1364. if self.updating_adjustments:
  1365. return
  1366. self.updating_adjustments = True
  1367. if self.hscroll.get_property('visible'):
  1368. try:
  1369. zoomratio = float(self.currimg_width)/self.previmg_width
  1370. newvalue = abs(self.layout.get_hadjustment().get_value() * zoomratio + (self.available_image_width()) * (zoomratio - 1) / 2)
  1371. if newvalue >= self.layout.get_hadjustment().lower and newvalue <= (self.layout.get_hadjustment().upper - self.layout.get_hadjustment().page_size):
  1372. self.layout.get_hadjustment().set_value(newvalue)
  1373. except:
  1374. pass
  1375. if self.vscroll.get_property('visible'):
  1376. try:
  1377. newvalue = abs(self.layout.get_vadjustment().get_value() * zoomratio + (self.available_image_height()) * (zoomratio - 1) / 2)
  1378. if newvalue >= self.layout.get_vadjustment().lower and newvalue <= (self.layout.get_vadjustment().upper - self.layout.get_vadjustment().page_size):
  1379. self.layout.get_vadjustment().set_value(newvalue)
  1380. self.previmg_width = self.currimg_width
  1381. except:
  1382. pass
  1383. self.updating_adjustments = False
  1384. def window_resized(self, widget, allocation, force_update=False):
  1385. # Update the image size on window resize if the current image was last fit:
  1386. if self.image_loaded:
  1387. if force_update or allocation.width != self.prevwinwidth or allocation.height != self.prevwinheight:
  1388. if self.last_image_action_was_fit:
  1389. if self.last_image_action_was_smart_fit:
  1390. self.zoom_to_fit_or_1_to_1(None, False, False)
  1391. else:
  1392. self.zoom_to_fit_window(None, False, False)
  1393. else:
  1394. self.center_image()
  1395. self.load_new_image_stop_now()
  1396. self.show_scrollbars_if_needed()
  1397. # Also, regenerate preloaded image for new window size:
  1398. self.preload_when_idle = gobject.idle_add(self.preload_next_image, True)
  1399. self.preload_when_idle2 = gobject.idle_add(self.preload_prev_image, True)
  1400. self.prevwinwidth = allocation.width
  1401. self.prevwinheight = allocation.height
  1402. return
  1403. def save_settings(self):
  1404. conf = ConfigParser.ConfigParser()
  1405. conf.add_section('window')
  1406. conf.set('window', 'w', self.window.get_allocation().width)
  1407. conf.set('window', 'h', self.window.get_allocation().height)
  1408. conf.set('window', 'toolbar', self.toolbar_show)
  1409. conf.set('window', 'statusbar', self.statusbar_show)
  1410. conf.set('window', 'thumbpane', self.thumbpane_show)
  1411. conf.add_section('prefs')
  1412. conf.set('prefs', 'simple-bgcolor', self.simple_bgcolor)
  1413. conf.set('prefs', 'bgcolor-red', self.bgcolor.red)
  1414. conf.set('prefs', 'bgcolor-green', self.bgcolor.green)
  1415. conf.set('prefs', 'bgcolor-blue', self.bgcolor.blue)
  1416. conf.set('prefs', 'open_all', self.open_all_images)
  1417. conf.set('prefs', 'hidden', self.open_hidden_files)
  1418. conf.set('prefs', 'use_last_dir', self.use_last_dir)
  1419. conf.set('prefs', 'last_dir', self.last_dir)
  1420. conf.set('prefs', 'fixed_dir', self.fixed_dir)
  1421. conf.set('prefs', 'open_mode', self.open_mode)
  1422. conf.set('prefs', 'last_mode', self.last_mode)
  1423. conf.set('prefs', 'listwrap_mode', self.listwrap_mode)
  1424. conf.set('prefs', 'slideshow_delay', int(self.slideshow_delay))
  1425. conf.set('prefs', 'slideshow_random', self.slideshow_random)
  1426. conf.set('prefs', 'zoomquality', self.zoomvalue)
  1427. conf.set('prefs', 'quality_save', int(self.quality_save))
  1428. conf.set('prefs', 'disable_screensaver', self.disable_screensaver)
  1429. conf.set('prefs', 'slideshow_in_fullscreen', self.slideshow_in_fullscreen)
  1430. conf.set('prefs', 'confirm_delete', self.confirm_delete)
  1431. conf.set('prefs', 'preloading_images', self.preloading_images)
  1432. conf.set('prefs', 'savemode', self.savemode)
  1433. conf.set('prefs', 'start_in_fullscreen', self.start_in_fullscreen)
  1434. conf.set('prefs', 'thumbsize', self.thumbnail_size)
  1435. conf.set('prefs', 'screenshot_delay', self.screenshot_delay)
  1436. conf.add_section('actions')
  1437. conf.set('actions', 'num_actions', len(self.action_names))
  1438. for i in range(len(self.action_names)):
  1439. conf.set('actions', 'names[' + str(i) + ']', self.action_names[i])
  1440. conf.set('actions', 'commands[' + str(i) + ']', self.action_commands[i])
  1441. conf.set('actions', 'shortcuts[' + str(i) + ']', self.action_shortcuts[i])
  1442. conf.set('actions', 'batch[' + str(i) + ']', self.action_batch[i])
  1443. conf.add_section('recent')
  1444. conf.set('recent', 'num_recent', len(self.recentfiles))
  1445. for i in range(len(self.recentfiles)):
  1446. conf.set('recent', 'num[' + str(i) + ']', len(self.recentfiles[i]))
  1447. conf.set('recent', 'urls[' + str(i) + ',0]', self.recentfiles[i])
  1448. if not os.path.exists(self.config_dir):
  1449. os.makedirs(self.config_dir)
  1450. conf.write(file(self.config_dir + '/miragerc', 'w'))
  1451. # Also, save accel_map:
  1452. gtk.accel_map_save(self.config_dir + '/accel_map')
  1453. return
  1454. def delete_event(self, widget, event, data=None):
  1455. cancel = self.autosave_image()
  1456. if cancel:
  1457. return True
  1458. self.stop_now = True
  1459. self.closing_app = True
  1460. self.save_settings()
  1461. sys.exit(0)
  1462. def destroy(self, event, data=None):
  1463. cancel = self.autosave_image()
  1464. if cancel:
  1465. return True
  1466. self.stop_now = True
  1467. self.closing_app = True
  1468. self.save_settings()
  1469. def exit_app(self, action):
  1470. cancel = self.autosave_image()
  1471. if cancel:
  1472. return True
  1473. self.stop_now = True
  1474. self.closing_app = True
  1475. self.save_settings()
  1476. sys.exit(0)
  1477. def put_zoom_image_to_window(self, currimg_preloaded):
  1478. self.window.window.freeze_updates()
  1479. if not currimg_preloaded:
  1480. # Always start with the original image to preserve quality!
  1481. # Calculate image size:
  1482. finalimg_width = int(self.currimg_pixbuf_original.get_width() * self.currimg_zoomratio)
  1483. finalimg_height = int(self.currimg_pixbuf_original.get_height() * self.currimg_zoomratio)
  1484. if not self.currimg_is_animation:
  1485. # Scale image:
  1486. if not self.currimg_pixbuf_original.get_has_alpha():
  1487. self.currimg_pixbuf = self.currimg_pixbuf_original.scale_simple(finalimg_width, finalimg_height, self.zoom_quality)
  1488. else:
  1489. colormap = self.imageview.get_colormap()
  1490. light_grey = colormap.alloc_color('#666666', True, True)
  1491. dark_grey = colormap.alloc_color('#999999', True, True)
  1492. self.currimg_pixbuf = self.currimg_pixbuf_original.composite_color_simple(finalimg_width, finalimg_height, self.zoom_quality, 255, 8, light_grey.pixel, dark_grey.pixel)
  1493. else:
  1494. self.currimg_pixbuf = self.currimg_pixbuf_original
  1495. self.currimg_width, self.currimg_height = finalimg_width, finalimg_height
  1496. self.layout.set_size(self.currimg_width, self.currimg_height)
  1497. self.center_image()
  1498. self.show_scrollbars_if_needed()
  1499. if not self.currimg_is_animation:
  1500. self.imageview.set_from_pixbuf(self.currimg_pixbuf)
  1501. self.previmage_is_animation = False
  1502. else:
  1503. self.imageview.set_from_animation(self.currimg_pixbuf)
  1504. self.previmage_is_animation = True
  1505. # Clean up (free memory) because I'm lazy
  1506. gc.collect()
  1507. self.window.window.thaw_updates()
  1508. self.loaded_img_in_list = self.curr_img_in_list
  1509. def show_scrollbars_if_needed(self):
  1510. if self.currimg_width > self.available_image_width():
  1511. self.hscroll.show()
  1512. else:
  1513. self.hscroll.hide()
  1514. if self.currimg_height > self.available_image_height():
  1515. self.vscroll.show()
  1516. else:
  1517. self.vscroll.hide()
  1518. def center_image(self):
  1519. x_shift = int((self.available_image_width() - self.currimg_width)/2)
  1520. if x_shift < 0:
  1521. x_shift = 0
  1522. y_shift = int((self.available_image_height() - self.currimg_height)/2)
  1523. if y_shift < 0:
  1524. y_shift = 0
  1525. self.layout.move(self.imageview, x_shift, y_shift)
  1526. def available_image_width(self):
  1527. width = self.window.get_size()[0]
  1528. if not self.fullscreen_mode:
  1529. if self.thumbpane_show:
  1530. width -= self.thumbscroll.size_request()[0]
  1531. return width
  1532. def available_image_height(self):
  1533. height = self.window.get_size()[1]
  1534. if not self.fullscreen_mode:
  1535. height -= self.menubar.size_request()[1]
  1536. if self.toolbar_show:
  1537. height -= self.toolbar.size_request()[1]
  1538. if self.statusbar_show:
  1539. height -= self.statusbar.size_request()[1]
  1540. return height
  1541. def save_image(self, action):
  1542. if self.UIManager.get_widget('/MainMenu/FileMenu/Save').get_property('sensitive'):
  1543. self.save_image_now(self.currimg_name, gtk.gdk.pixbuf_get_file_info(self.currimg_name)[0]['name'])
  1544. def save_image_as(self, action):
  1545. dialog = gtk.FileChooserDialog(title=_("Save As"),action=gtk.FILE_CHOOSER_ACTION_SAVE,buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK))
  1546. dialog.set_default_response(gtk.RESPONSE_OK)
  1547. filename = os.path.basename(self.currimg_name)
  1548. filetype = None
  1549. dialog.set_current_folder(os.path.dirname(self.currimg_name))
  1550. dialog.set_current_name(filename)
  1551. dialog.set_do_overwrite_confirmation(True)
  1552. response = dialog.run()
  1553. if response == gtk.RESPONSE_OK:
  1554. prev_name = self.currimg_name
  1555. filename = dialog.get_filename()
  1556. dialog.destroy()
  1557. fileext = os.path.splitext(os.path.basename(filename))[1].lower()
  1558. if len(fileext) > 0:
  1559. fileext = fileext[1:]
  1560. # Override filetype if user typed a filename with a different extension:
  1561. for i in gtk.gdk.pixbuf_get_formats():
  1562. if fileext in i['extensions']:
  1563. filetype = i['name']
  1564. self.save_image_now(filename, filetype)
  1565. self.register_file_with_recent_docs(filename)
  1566. else:
  1567. dialog.destroy()
  1568. def save_image_now(self, dest_name, filetype):
  1569. try:
  1570. self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
  1571. while gtk.events_pending():
  1572. gtk.main_iteration()
  1573. if filetype == None:
  1574. filetype = gtk.gdk.pixbuf_get_file_info(self.currimg_name)[0]['name']
  1575. if self.filetype_is_writable(filetype):
  1576. self.currimg_pixbuf_original.save(dest_name, filetype, {'quality': str(self.quality_save)})
  1577. self.currimg_name = dest_name
  1578. self.image_list[self.curr_img_in_list] = dest_name
  1579. self.update_title()
  1580. self.update_statusbar()
  1581. # Update thumbnail:
  1582. gobject.idle_add(self.thumbpane_set_image, dest_name, self.curr_img_in_list, True)
  1583. self.image_modified = False
  1584. else:
  1585. error_dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO, _('The %s format is not supported for saving. Do you wish to save the file in a different format?') % filetype)
  1586. error_dialog.set_title(_("Save"))
  1587. response = error_dialog.run()
  1588. if response == gtk.RESPONSE_YES:
  1589. error_dialog.destroy()
  1590. while gtk.events_pending():
  1591. gtk.main_iteration()
  1592. self.save_image_as(None)
  1593. else:
  1594. error_dialog.destroy()
  1595. except:
  1596. error_dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, _('Unable to save %s') % dest_name)
  1597. error_dialog.set_title(_("Save"))
  1598. error_dialog.run()
  1599. error_dialog.destroy()
  1600. self.change_cursor(None)
  1601. def autosave_image(self):
  1602. # Returns True if the user has canceled out of the dialog
  1603. # Never call this function from an idle or timeout loop! That will cause
  1604. # the app to freeze.
  1605. if self.image_modified:
  1606. if self.savemode == 1:
  1607. temp = self.UIManager.get_widget('/MainMenu/FileMenu/Save').get_property('sensitive')
  1608. self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_property('sensitive', True)
  1609. self.save_image(None)
  1610. self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_property('sensitive', temp)
  1611. elif self.savemode == 2:
  1612. dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, _("The current image has been modified. Save changes?"))
  1613. dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
  1614. dialog.add_button(gtk.STOCK_NO, gtk.RESPONSE_NO)
  1615. dialog.add_button(gtk.STOCK_SAVE, gtk.RESPONSE_YES)
  1616. dialog.set_title(_("Save?"))
  1617. dialog.set_default_response(gtk.RESPONSE_YES)
  1618. response = dialog.run()
  1619. dialog.destroy()
  1620. if response == gtk.RESPONSE_YES:
  1621. temp = self.UIManager.get_widget('/MainMenu/FileMenu/Save').get_property('sensitive')
  1622. self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_property('sensitive', True)
  1623. self.save_image(None)
  1624. self.UIManager.get_widget('/MainMenu/FileMenu/Save').set_property('sensitive', temp)
  1625. self.image_modified = False
  1626. elif response == gtk.RESPONSE_NO:
  1627. self.image_modified = False
  1628. # Ensures that we don't use the current pixbuf for any preload pixbufs if we are in
  1629. # the process of loading the previous or next image in the list:
  1630. self.currimg_pixbuf = self.currimg_pixbuf_original
  1631. self.preloadimg_next_in_list = -1
  1632. self.preloadimg_prev_in_list = -1
  1633. self.loaded_img_in_list = -1
  1634. else:
  1635. return True
  1636. def filetype_is_writable(self, filetype):
  1637. # Determine if filetype is a writable format
  1638. filetype_is_writable = True
  1639. for i in gtk.gdk.pixbuf_get_formats():
  1640. if filetype in i['extensions']:
  1641. if i['is_writable']:
  1642. return True
  1643. return False
  1644. def open_file(self, action):
  1645. self.stop_now = True
  1646. while gtk.events_pending():
  1647. gtk.main_iteration()
  1648. self.open_file_or_folder(action, True)
  1649. def open_file_remote(self, action):
  1650. # Prompt user for the url:
  1651. dialog = gtk.Dialog(_("Open Remote"), self.window, gtk.DIALOG_MODAL, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
  1652. location = gtk.Entry()
  1653. location.set_size_request(300, -1)
  1654. location.set_activates_default(True)
  1655. hbox = gtk.HBox()
  1656. hbox.pack_start(gtk.Label(_("Image Location (URL):")), False, False, 5)
  1657. hbox.pack_start(location, True, True, 5)
  1658. dialog.vbox.pack_start(hbox, True, True, 10)
  1659. dialog.set_default_response(gtk.RESPONSE_OK)
  1660. dialog.vbox.show_all()
  1661. dialog.connect('response', self.open_file_remote_response, location)
  1662. response = dialog.show()
  1663. def open_file_remote_response(self, dialog, response, location):
  1664. if response == gtk.RESPONSE_OK:
  1665. filenames = []
  1666. filenames.append(location.get_text())
  1667. dialog.destroy()
  1668. while gtk.events_pending():
  1669. gtk.main_iteration()
  1670. self.expand_filelist_and_load_image(filenames)
  1671. else:
  1672. dialog.destroy()
  1673. def open_folder(self, action):
  1674. self.stop_now = True
  1675. while gtk.events_pending():
  1676. gtk.main_iteration()
  1677. self.open_file_or_folder(action, False)
  1678. def open_file_or_folder(self, action, isfile):
  1679. self.thumbpane_create_dir()
  1680. cancel = self.autosave_image()
  1681. if cancel:
  1682. return
  1683. # If isfile = True, file; If isfile = False, folder
  1684. dialog = gtk.FileChooserDialog(title=_("Open"),action=gtk.FILE_CHOOSER_ACTION_OPEN,buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
  1685. if isfile:
  1686. filter = gtk.FileFilter()
  1687. filter.set_name(_("Images"))
  1688. filter.add_pixbuf_formats()
  1689. dialog.add_filter(filter)
  1690. filter = gtk.FileFilter()
  1691. filter.set_name(_("All files"))
  1692. filter.add_pattern("*")
  1693. dialog.add_filter(filter)
  1694. preview = gtk.Image()
  1695. dialog.set_preview_widget(preview)
  1696. dialog.set_use_preview_label(False)
  1697. dialog.connect("update-preview", self.update_preview, preview)
  1698. recursivebutton = None
  1699. else:
  1700. dialog.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
  1701. recursivebutton = gtk.CheckButton(label=_("Include images in subdirectories"))
  1702. dialog.set_extra_widget(recursivebutton)
  1703. dialog.set_default_response(gtk.RESPONSE_OK)
  1704. dialog.set_select_multiple(True)
  1705. if self.use_last_dir:
  1706. if self.last_dir != None:
  1707. dialog.set_current_folder(self.last_dir)
  1708. else:
  1709. if self.fixed_dir != None:
  1710. dialog.set_current_folder(self.fixed_dir)
  1711. dialog.connect("response", self.open_file_or_folder_response, isfile, recursivebutton)
  1712. response = dialog.show()
  1713. def open_file_or_folder_response(self, dialog, response, isfile, recursivebutton):
  1714. if response == gtk.RESPONSE_OK:
  1715. if self.use_last_dir:
  1716. self.last_dir = dialog.get_current_folder()
  1717. if not isfile and recursivebutton.get_property('active'):
  1718. self.recursive = True
  1719. filenames = dialog.get_filenames()
  1720. dialog.destroy()
  1721. while gtk.events_pending():
  1722. gtk.main_iteration()
  1723. self.expand_filelist_and_load_image(filenames)
  1724. else:
  1725. dialog.destroy()
  1726. def update_preview(self, file_chooser, preview):
  1727. filename = file_chooser.get_preview_filename()
  1728. if not filename:
  1729. return
  1730. filename, thumbfile = self.thumbnail_get_name(filename)
  1731. pixbuf = self.thumbpane_get_pixbuf(thumbfile, filename, False)
  1732. if pixbuf:
  1733. preview.set_from_pixbuf(pixbuf)
  1734. else:
  1735. pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 1, 8, 128, 128)
  1736. pixbuf.fill(0x00000000)
  1737. preview.set_from_pixbuf(pixbuf)
  1738. have_preview = True
  1739. file_chooser.set_preview_widget_active(have_preview)
  1740. del pixbuf
  1741. gc.collect()
  1742. def hide_cursor(self):
  1743. if self.fullscreen_mode and not self.user_prompt_visible and not self.slideshow_controls_visible:
  1744. pix_data = """/* XPM */
  1745. static char * invisible_xpm[] = {
  1746. "1 1 1 1",
  1747. " c None",
  1748. " "};"""
  1749. color = gtk.gdk.Color()
  1750. pix = gtk.gdk.pixmap_create_from_data(None, pix_data, 1, 1, 1, color, color)
  1751. invisible = gtk.gdk.Cursor(pix, pix, color, color, 0, 0)
  1752. self.change_cursor(invisible)
  1753. return False
  1754. def enter_fullscreen(self, action):
  1755. if not self.fullscreen_mode:
  1756. self.fullscreen_mode = True
  1757. self.UIManager.get_widget('/Popup/Full Screen').hide()
  1758. self.UIManager.get_widget('/Popup/Exit Full Screen').show()
  1759. self.statusbar.hide()
  1760. self.statusbar2.hide()
  1761. self.toolbar.hide()
  1762. self.menubar.hide()
  1763. self.thumbscroll.hide()
  1764. self.thumbpane.hide()
  1765. self.window.fullscreen()
  1766. self.timer_id = gobject.timeout_add(2000, self.hide_cursor)
  1767. self.set_slideshow_sensitivities()
  1768. if self.simple_bgcolor:
  1769. self.layout.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
  1770. else:
  1771. if self.simple_bgcolor:
  1772. self.layout.modify_bg(gtk.STATE_NORMAL, None)
  1773. self.leave_fullscreen(action)
  1774. def leave_fullscreen(self, action):
  1775. if self.fullscreen_mode:
  1776. self.slideshow_controls_visible = False
  1777. self.slideshow_window.hide_all()
  1778. self.slideshow_window2.hide_all()
  1779. self.fullscreen_mode = False
  1780. self.UIManager.get_widget('/Popup/Full Screen').show()
  1781. self.UIManager.get_widget('/Popup/Exit Full Screen').hide()
  1782. if self.toolbar_show:
  1783. self.toolbar.show()
  1784. self.menubar.show()
  1785. if self.statusbar_show:
  1786. self.statusbar.show()
  1787. self.statusbar2.show()
  1788. if self.thumbpane_show:
  1789. self.thumbscroll.show()
  1790. self.thumbpane.show()
  1791. self.thumbpane_update_images(False, self.curr_img_in_list)
  1792. self.window.unfullscreen()
  1793. self.change_cursor(None)
  1794. self.set_slideshow_sensitivities()
  1795. if self.simple_bgcolor:
  1796. self.layout.modify_bg(gtk.STATE_NORMAL, None)
  1797. def toggle_status_bar(self, action):
  1798. if self.statusbar.get_property('visible'):
  1799. self.statusbar.hide()
  1800. self.statusbar2.hide()
  1801. self.statusbar_show = False
  1802. else:
  1803. self.statusbar.show()
  1804. self.statusbar2.show()
  1805. self.statusbar_show = True
  1806. if self.image_loaded and self.last_image_action_was_fit:
  1807. if self.last_image_action_was_smart_fit:
  1808. self.zoom_to_fit_or_1_to_1(None, False, False)
  1809. else:
  1810. self.zoom_to_fit_window(None, False, False)
  1811. def toggle_thumbpane(self, action):
  1812. if self.thumbscroll.get_property('visible'):
  1813. self.thumbscroll.hide()
  1814. self.thumbpane.hide()
  1815. self.thumbpane_show = False
  1816. else:
  1817. self.thumbscroll.show()
  1818. self.thumbpane.show()
  1819. self.thumbpane_show = True
  1820. self.stop_now = False
  1821. gobject.idle_add(self.thumbpane_update_images, True, self.curr_img_in_list)
  1822. if self.image_loaded and self.last_image_action_was_fit:
  1823. if self.last_image_action_was_smart_fit:
  1824. self.zoom_to_fit_or_1_to_1(None, False, False)
  1825. else:
  1826. self.zoom_to_fit_window(None, False, False)
  1827. def toggle_toolbar(self, action):
  1828. if self.toolbar.get_property('visible'):
  1829. self.toolbar.hide()
  1830. self.toolbar_show = False
  1831. else:
  1832. self.toolbar.show()
  1833. self.toolbar_show = True
  1834. if self.image_loaded and self.last_image_action_was_fit:
  1835. if self.last_image_action_was_smart_fit:
  1836. self.zoom_to_fit_or_1_to_1(None, False, False)
  1837. else:
  1838. self.zoom_to_fit_window(None, False, False)
  1839. def update_statusbar(self):
  1840. # Update status bar:
  1841. try:
  1842. st = os.stat(self.currimg_name)
  1843. filesize = st[stat.ST_SIZE]/1000
  1844. ratio = int(100 * self.currimg_zoomratio)
  1845. status_text = os.path.basename(self.currimg_name)+ ": " + str(self.currimg_pixbuf_original.get_width()) + "x" + str(self.currimg_pixbuf_original.get_height()) + " " + str(filesize) + "KB " + str(ratio) + "% "
  1846. except:
  1847. status_text=_("Cannot load image.")
  1848. self.statusbar.push(self.statusbar.get_context_id(""), status_text)
  1849. status_text = ""
  1850. if self.running_custom_actions:
  1851. status_text = _('Custom actions: %(current)i of %(total)i') % {'current': self.curr_custom_action,'total': self.num_custom_actions}
  1852. elif self.searching_for_images:
  1853. status_text = _('Scanning...')
  1854. self.statusbar2.push(self.statusbar2.get_context_id(""), status_text)
  1855. def show_custom_actions(self, action):
  1856. self.actions_dialog = gtk.Dialog(title=_("Configure Custom Actions"), parent=self.window)
  1857. self.actions_dialog.set_has_separator(False)
  1858. self.actions_dialog.set_resizable(False)
  1859. table_actions = gtk.Table(13, 2, False)
  1860. table_actions.attach(gtk.Label(), 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  1861. actionscrollwindow = gtk.ScrolledWindow()
  1862. self.actionstore = gtk.ListStore(str, str, str)
  1863. self.actionwidget = gtk.TreeView()
  1864. self.actionwidget.set_enable_search(False)
  1865. self.actionwidget.set_rules_hint(True)
  1866. self.actionwidget.connect('row-activated', self.edit_custom_action2)
  1867. actionscrollwindow.add(self.actionwidget)
  1868. actionscrollwindow.set_shadow_type(gtk.SHADOW_IN)
  1869. actionscrollwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
  1870. actionscrollwindow.set_size_request(500, 200)
  1871. self.actionwidget.set_model(self.actionstore)
  1872. self.cell = gtk.CellRendererText()
  1873. self.cellbool = gtk.CellRendererPixbuf()
  1874. self.tvcolumn0 = gtk.TreeViewColumn(_("Batch"))
  1875. self.tvcolumn1 = gtk.TreeViewColumn(_("Action"), self.cell, markup=0)
  1876. self.tvcolumn2 = gtk.TreeViewColumn(_("Shortcut"))
  1877. self.tvcolumn1.set_max_width(self.actionwidget.size_request()[0] - self.tvcolumn0.get_width() - self.tvcolumn2.get_width())
  1878. self.actionwidget.append_column(self.tvcolumn0)
  1879. self.actionwidget.append_column(self.tvcolumn1)
  1880. self.actionwidget.append_column(self.tvcolumn2)
  1881. self.populate_treeview()
  1882. if len(self.action_names) > 0:
  1883. self.actionwidget.get_selection().select_path(0)
  1884. vbox_actions = gtk.VBox()
  1885. addbutton = gtk.Button("", gtk.STOCK_ADD)
  1886. addbutton.get_child().get_child().get_children()[1].set_text('')
  1887. addbutton.connect('clicked', self.add_custom_action, self.actionwidget)
  1888. addbutton.set_tooltip_text(_("Add action"))
  1889. editbutton = gtk.Button("", gtk.STOCK_EDIT)
  1890. editbutton.get_child().get_child().get_children()[1].set_text('')
  1891. editbutton.connect('clicked', self.edit_custom_action, self.actionwidget)
  1892. editbutton.set_tooltip_text(_("Edit selected action."))
  1893. removebutton = gtk.Button("", gtk.STOCK_REMOVE)
  1894. removebutton.get_child().get_child().get_children()[1].set_text('')
  1895. removebutton.connect('clicked', self.remove_custom_action)
  1896. removebutton.set_tooltip_text(_("Remove selected action."))
  1897. upbutton = gtk.Button("", gtk.STOCK_GO_UP)
  1898. upbutton.get_child().get_child().get_children()[1].set_text('')
  1899. upbutton.connect('clicked', self.custom_action_move_up, self.actionwidget)
  1900. upbutton.set_tooltip_text(_("Move selected action up."))
  1901. downbutton = gtk.Button("", gtk.STOCK_GO_DOWN)
  1902. downbutton.get_child().get_child().get_children()[1].set_text('')
  1903. downbutton.connect('clicked', self.custom_action_move_down, self.actionwidget)
  1904. downbutton.set_tooltip_text(_("Move selected action down."))
  1905. vbox_buttons = gtk.VBox()
  1906. propertyinfo = gtk.Label()
  1907. propertyinfo.set_markup('<small>' + _("Parametreler") + ':\n<span font_family="Monospace">%F</span> - ' + _("File path, name, and extension") + '\n<span font_family="Monospace">%P</span> - ' + _("File path") + '\n<span font_family="Monospace">%N</span> - ' + _("File name without file extension") + '\n<span font_family="Monospace">%E</span> - ' + _("File extension (i.e. \".png\")") + '\n<span font_family="Monospace">%L</span> - ' + _("List of files, space-separated") + '</small>')
  1908. propertyinfo.set_alignment(0, 0)
  1909. actioninfo = gtk.Label()
  1910. actioninfo.set_markup('<small>' + _("İşlemler") + ':\n<span font_family="Monospace">[NEXT]</span> - ' + _("Go to next image") + '\n<span font_family="Monospace">[PREV]</span> - ' + _("Go to previous image") +'</small>')
  1911. actioninfo.set_alignment(0, 0)
  1912. hbox_info = gtk.HBox()
  1913. hbox_info.pack_start(propertyinfo, False, False, 15)
  1914. hbox_info.pack_start(actioninfo, False, False, 15)
  1915. vbox_buttons.pack_start(addbutton, False, False, 5)
  1916. vbox_buttons.pack_start(editbutton, False, False, 5)
  1917. vbox_buttons.pack_start(removebutton, False, False, 5)
  1918. vbox_buttons.pack_start(upbutton, False, False, 5)
  1919. vbox_buttons.pack_start(downbutton, False, False, 0)
  1920. hbox_top = gtk.HBox()
  1921. hbox_top.pack_start(actionscrollwindow, True, True, 5)
  1922. hbox_top.pack_start(vbox_buttons, False, False, 5)
  1923. vbox_actions.pack_start(hbox_top, True, True, 5)
  1924. vbox_actions.pack_start(hbox_info, False, False, 5)
  1925. hbox_instructions = gtk.HBox()
  1926. info_image = gtk.Image()
  1927. info_image.set_from_stock(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_BUTTON)
  1928. hbox_instructions.pack_start(info_image, False, False, 5)
  1929. instructions = gtk.Label(_("Burada kısayollarla özel eylemleri tanımlayabilirsiniz. Eylemler, aşağıda listelenen yerleşik parametreleri ve işlemleri kullanır ve noktalı virgülle ayrılmış birden çok ifadeye sahip olabilir. Toplu işlemler, listedeki tüm görüntülere uygulanır."))
  1930. instructions.set_line_wrap(True)
  1931. instructions.set_alignment(0, 0.5)
  1932. hbox_instructions.pack_start(instructions, False, False, 5)
  1933. table_actions.attach(hbox_instructions, 1, 3, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 5, 0)
  1934. table_actions.attach(gtk.Label(), 1, 3, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  1935. table_actions.attach(vbox_actions, 1, 3, 4, 12, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  1936. table_actions.attach(gtk.Label(), 1, 3, 12, 13, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  1937. self.actions_dialog.vbox.pack_start(table_actions, False, False, 0)
  1938. # Show dialog:
  1939. self.actions_dialog.vbox.show_all()
  1940. instructions.set_size_request(self.actions_dialog.size_request()[0]-50, -1)
  1941. close_button = self.actions_dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
  1942. close_button.grab_focus()
  1943. self.actions_dialog.run()
  1944. self.refresh_custom_actions_menu()
  1945. while gtk.events_pending():
  1946. gtk.main_iteration()
  1947. if len(self.image_list) == 0:
  1948. self.set_image_sensitivities(False)
  1949. self.actions_dialog.destroy()
  1950. def add_custom_action(self, button, treeview):
  1951. self.open_custom_action_dialog(True, '', '', 'None', False, treeview)
  1952. def edit_custom_action2(self, treeview, path, view_column):
  1953. self.edit_custom_action(None, treeview)
  1954. def edit_custom_action(self, button, treeview):
  1955. (model, iter) = self.actionwidget.get_selection().get_selected()
  1956. if iter != None:
  1957. (row, ) = self.actionstore.get_path(iter)
  1958. self.open_custom_action_dialog(False, self.action_names[row], self.action_commands[row], self.action_shortcuts[row], self.action_batch[row], treeview)
  1959. def open_custom_action_dialog(self, add_call, name, command, shortcut, batch, treeview):
  1960. if add_call:
  1961. self.dialog_name = gtk.Dialog(_("Add Custom Action"), self.actions_dialog, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
  1962. else:
  1963. self.dialog_name = gtk.Dialog(_("Edit Custom Action"), self.actions_dialog, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
  1964. self.dialog_name.set_modal(True)
  1965. table = gtk.Table(2, 4, False)
  1966. action_name_label = gtk.Label(_("İşlem Adı:"))
  1967. action_name_label.set_alignment(0, 0.5)
  1968. action_command_label = gtk.Label(_("Komut:"))
  1969. action_command_label.set_alignment(0, 0.5)
  1970. shortcut_label = gtk.Label(_("Kısayol:"))
  1971. shortcut_label.set_alignment(0, 0.5)
  1972. table.attach(action_name_label, 0, 1, 0, 1, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  1973. table.attach(action_command_label, 0, 1, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  1974. table.attach(shortcut_label, 0, 1, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  1975. action_name = gtk.Entry()
  1976. action_name.set_text(name)
  1977. action_command = gtk.Entry()
  1978. action_command.set_text(command)
  1979. table.attach(action_name, 1, 2, 0, 1, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  1980. table.attach(action_command, 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  1981. self.shortcut = gtk.Button(shortcut)
  1982. self.shortcut.connect('clicked', self.shortcut_clicked)
  1983. table.attach(self.shortcut, 1, 2, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  1984. batchmode = gtk.CheckButton(_("Perform action on all images (Batch)"))
  1985. batchmode.set_active(batch)
  1986. table.attach(batchmode, 0, 2, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  1987. self.dialog_name.vbox.pack_start(table, False, False, 5)
  1988. self.dialog_name.vbox.show_all()
  1989. self.dialog_name.connect('response', self.dialog_name_response, add_call, action_name, action_command, self.shortcut, batchmode, treeview)
  1990. self.dialog_name.run()
  1991. def dialog_name_response(self, dialog, response, add_call, action_name, action_command, shortcut, batchmode, treeview):
  1992. if response == gtk.RESPONSE_ACCEPT:
  1993. if not (action_command.get_text() == "" or action_name.get_text() == "" or self.shortcut.get_label() == "None"):
  1994. name = action_name.get_text()
  1995. command = action_command.get_text()
  1996. if ((("[NEXT]" in command.strip()) and command.strip()[-6:] != "[NEXT]") or (("[PREV]" in command.strip()) and command.strip()[-6:] != "[PREV]") ):
  1997. error_dialog = gtk.MessageDialog(self.actions_dialog, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, _('[PREV] and [NEXT] are only valid alone or at the end of the command'))
  1998. error_dialog.set_title(_("Invalid Custom Action"))
  1999. error_dialog.run()
  2000. error_dialog.destroy()
  2001. return
  2002. shortcut = shortcut.get_label()
  2003. batch = batchmode.get_active()
  2004. dialog.destroy()
  2005. if add_call:
  2006. self.action_names.append(name)
  2007. self.action_commands.append(command)
  2008. self.action_shortcuts.append(shortcut)
  2009. self.action_batch.append(batch)
  2010. else:
  2011. (model, iter) = self.actionwidget.get_selection().get_selected()
  2012. (rownum, ) = self.actionstore.get_path(iter)
  2013. self.action_names[rownum] = name
  2014. self.action_commands[rownum] = command
  2015. self.action_shortcuts[rownum] = shortcut
  2016. self.action_batch[rownum] = batch
  2017. self.populate_treeview()
  2018. if add_call:
  2019. rownum = len(self.action_names)-1
  2020. treeview.get_selection().select_path(rownum)
  2021. while gtk.events_pending():
  2022. gtk.main_iteration()
  2023. # Keep item in visible rect:
  2024. visible_rect = treeview.get_visible_rect()
  2025. row_rect = treeview.get_background_area(rownum, self.tvcolumn1)
  2026. if row_rect.y + row_rect.height > visible_rect.height:
  2027. top_coord = (row_rect.y + row_rect.height - visible_rect.height) + visible_rect.y
  2028. treeview.scroll_to_point(-1, top_coord)
  2029. elif row_rect.y < 0:
  2030. treeview.scroll_to_cell(rownum)
  2031. else:
  2032. error_dialog = gtk.MessageDialog(self.actions_dialog, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, _('Incomplete custom action specified.'))
  2033. error_dialog.set_title(_("Invalid Custom Action"))
  2034. error_dialog.run()
  2035. error_dialog.destroy()
  2036. else:
  2037. dialog.destroy()
  2038. def custom_action_move_down(self, button, treeview):
  2039. iter = None
  2040. selection = treeview.get_selection()
  2041. model, iter = selection.get_selected()
  2042. if iter:
  2043. rownum = int(model.get_string_from_iter(iter))
  2044. if rownum < len(self.action_names)-1:
  2045. # Move item down:
  2046. temp_name = self.action_names[rownum]
  2047. temp_shortcut = self.action_shortcuts[rownum]
  2048. temp_command = self.action_commands[rownum]
  2049. temp_batch = self.action_batch[rownum]
  2050. self.action_names[rownum] = self.action_names[rownum+1]
  2051. self.action_shortcuts[rownum] = self.action_shortcuts[rownum+1]
  2052. self.action_commands[rownum] = self.action_commands[rownum+1]
  2053. self.action_batch[rownum] = self.action_batch[rownum+1]
  2054. self.action_names[rownum+1] = temp_name
  2055. self.action_shortcuts[rownum+1] = temp_shortcut
  2056. self.action_commands[rownum+1] = temp_command
  2057. self.action_batch[rownum+1] = temp_batch
  2058. # Repopulate treeview and keep item selected:
  2059. self.populate_treeview()
  2060. selection.select_path((rownum+1,))
  2061. while gtk.events_pending():
  2062. gtk.main_iteration()
  2063. # Keep item in visible rect:
  2064. rownum = rownum + 1
  2065. visible_rect = treeview.get_visible_rect()
  2066. row_rect = treeview.get_background_area(rownum, self.tvcolumn1)
  2067. if row_rect.y + row_rect.height > visible_rect.height:
  2068. top_coord = (row_rect.y + row_rect.height - visible_rect.height) + visible_rect.y
  2069. treeview.scroll_to_point(-1, top_coord)
  2070. elif row_rect.y < 0:
  2071. treeview.scroll_to_cell(rownum)
  2072. def custom_action_move_up(self, button, treeview):
  2073. iter = None
  2074. selection = treeview.get_selection()
  2075. model, iter = selection.get_selected()
  2076. if iter:
  2077. rownum = int(model.get_string_from_iter(iter))
  2078. if rownum > 0:
  2079. # Move item down:
  2080. temp_name = self.action_names[rownum]
  2081. temp_shortcut = self.action_shortcuts[rownum]
  2082. temp_command = self.action_commands[rownum]
  2083. temp_batch = self.action_batch[rownum]
  2084. self.action_names[rownum] = self.action_names[rownum-1]
  2085. self.action_shortcuts[rownum] = self.action_shortcuts[rownum-1]
  2086. self.action_commands[rownum] = self.action_commands[rownum-1]
  2087. self.action_batch[rownum] = self.action_batch[rownum-1]
  2088. self.action_names[rownum-1] = temp_name
  2089. self.action_shortcuts[rownum-1] = temp_shortcut
  2090. self.action_commands[rownum-1] = temp_command
  2091. self.action_batch[rownum-1] = temp_batch
  2092. # Repopulate treeview and keep item selected:
  2093. self.populate_treeview()
  2094. selection.select_path((rownum-1,))
  2095. while gtk.events_pending():
  2096. gtk.main_iteration()
  2097. # Keep item in visible rect:
  2098. rownum = rownum - 1
  2099. visible_rect = treeview.get_visible_rect()
  2100. row_rect = treeview.get_background_area(rownum, self.tvcolumn1)
  2101. if row_rect.y + row_rect.height > visible_rect.height:
  2102. top_coord = (row_rect.y + row_rect.height - visible_rect.height) + visible_rect.y
  2103. treeview.scroll_to_point(-1, top_coord)
  2104. elif row_rect.y < 0:
  2105. treeview.scroll_to_cell(rownum)
  2106. def shortcut_clicked(self, widget):
  2107. self.dialog_shortcut = gtk.Dialog(_("İşlem Kısayolu"), self.dialog_name, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
  2108. self.shortcut_label = gtk.Label(_("Press the desired shortcut for the action."))
  2109. hbox = gtk.HBox()
  2110. hbox.pack_start(self.shortcut_label, False, False, 15)
  2111. self.dialog_shortcut.vbox.pack_start(hbox, False, False, 5)
  2112. self.dialog_shortcut.vbox.show_all()
  2113. self.dialog_shortcut.connect('key-press-event', self.shortcut_keypress)
  2114. self.dialog_shortcut.run()
  2115. self.dialog_shortcut.destroy()
  2116. def shortcut_keypress(self, widget, event):
  2117. shortcut = gtk.accelerator_name(event.keyval, event.state)
  2118. if "<Mod2>" in shortcut:
  2119. shortcut = shortcut.replace("<Mod2>", "")
  2120. if shortcut[(len(shortcut)-2):len(shortcut)] != "_L" and shortcut[(len(shortcut)-2):len(shortcut)] != "_R":
  2121. # Validate to make sure the shortcut hasn't already been used:
  2122. for i in range(len(self.keys)):
  2123. if shortcut == self.keys[i][1]:
  2124. error_dialog = gtk.MessageDialog(self.dialog_shortcut, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, _('The shortcut \'%(shortcut)s\' is already used for \'%(key)s\'.') % {'shortcut': shortcut, 'key': self.keys[i][0]})
  2125. error_dialog.set_title(_("Invalid Shortcut"))
  2126. error_dialog.run()
  2127. error_dialog.destroy()
  2128. return
  2129. for i in range(len(self.action_shortcuts)):
  2130. if shortcut == self.action_shortcuts[i]:
  2131. error_dialog = gtk.MessageDialog(self.dialog_shortcut, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, _('The shortcut \'%(shortcut)s\' is already used for \'%(key)s\'.') % {'shortcut': shortcut, 'key': self.action_names[i]})
  2132. error_dialog.set_title(_("Invalid Shortcut"))
  2133. error_dialog.run()
  2134. error_dialog.destroy()
  2135. return
  2136. self.shortcut.set_label(shortcut)
  2137. widget.destroy()
  2138. def remove_custom_action(self, button):
  2139. (model, iter) = self.actionwidget.get_selection().get_selected()
  2140. if iter != None:
  2141. (row, ) = self.actionstore.get_path(iter)
  2142. self.action_names.pop(row)
  2143. self.action_shortcuts.pop(row)
  2144. self.action_commands.pop(row)
  2145. self.action_batch.pop(row)
  2146. self.populate_treeview()
  2147. self.actionwidget.grab_focus()
  2148. def populate_treeview(self):
  2149. self.actionstore.clear()
  2150. for i in range(len(self.action_names)):
  2151. if self.action_batch[i]:
  2152. pb = gtk.STOCK_APPLY
  2153. else:
  2154. pb = None
  2155. self.actionstore.append([pb, '<big><b>' + self.action_names[i].replace('&','&amp;') + '</b></big>\n<small>' + self.action_commands[i].replace('&','&amp;') + '</small>', self.action_shortcuts[i]])
  2156. self.tvcolumn0.clear()
  2157. self.tvcolumn1.clear()
  2158. self.tvcolumn2.clear()
  2159. self.tvcolumn0.pack_start(self.cellbool)
  2160. self.tvcolumn1.pack_start(self.cell)
  2161. self.tvcolumn2.pack_start(self.cell)
  2162. self.tvcolumn0.add_attribute(self.cellbool, "stock-id", 0)
  2163. self.tvcolumn1.set_attributes(self.cell, markup=1)
  2164. self.tvcolumn2.set_attributes(self.cell, text=2)
  2165. self.tvcolumn1.set_expand(True)
  2166. def screenshot(self, action):
  2167. cancel = self.autosave_image()
  2168. if cancel:
  2169. return
  2170. # Dialog:
  2171. dialog = gtk.Dialog(_("Screenshot"), self.window, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
  2172. snapbutton = dialog.add_button(_("_Snap"), gtk.RESPONSE_ACCEPT)
  2173. snapimage = gtk.Image()
  2174. snapimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
  2175. snapbutton.set_image(snapimage)
  2176. loc = gtk.Label()
  2177. loc.set_markup('<b>' + _('Location') + '</b>')
  2178. loc.set_alignment(0, 0)
  2179. area = gtk.RadioButton()
  2180. area1 = gtk.RadioButton(group=area, label=_("Entire screen"))
  2181. area2 = gtk.RadioButton(group=area, label=_("Window under pointer"))
  2182. if not HAS_XMOUSE:
  2183. area2.set_sensitive(False)
  2184. area1.set_active(True)
  2185. de = gtk.Label()
  2186. de.set_markup('<b>' + _("Delay") + '</b>')
  2187. de.set_alignment(0, 0)
  2188. delaybox = gtk.HBox()
  2189. adj = gtk.Adjustment(self.screenshot_delay, 0, 30, 1, 10, 0)
  2190. delay = gtk.SpinButton(adj, 0, 0)
  2191. delay.set_numeric(True)
  2192. delay.set_update_policy(gtk.UPDATE_IF_VALID)
  2193. delay.set_wrap(False)
  2194. delaylabel = gtk.Label(_(" seconds"))
  2195. delaybox.pack_start(delay, False)
  2196. delaybox.pack_start(delaylabel, False)
  2197. table = gtk.Table()
  2198. table.attach(gtk.Label(), 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2199. table.attach(loc, 1, 2, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  2200. table.attach(gtk.Label(), 1, 2, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2201. table.attach(area1, 1, 2, 4, 5, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2202. table.attach(area2, 1, 2, 5, 6, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2203. table.attach(gtk.Label(), 1, 2, 6, 7, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2204. table.attach(de, 1, 2, 7, 8, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  2205. table.attach(gtk.Label(), 1, 2, 8, 9, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2206. table.attach(delaybox, 1, 2, 9, 10, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2207. table.attach(gtk.Label(), 1, 2, 10, 11, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2208. dialog.vbox.pack_start(table)
  2209. dialog.set_default_response(gtk.RESPONSE_ACCEPT)
  2210. dialog.vbox.show_all()
  2211. response = dialog.run()
  2212. if response == gtk.RESPONSE_ACCEPT:
  2213. dialog.destroy()
  2214. while gtk.events_pending():
  2215. gtk.main_iteration()
  2216. self.screenshot_delay = delay.get_value_as_int()
  2217. gobject.timeout_add(int(self.screenshot_delay*1000), self._screenshot_grab, area1.get_active())
  2218. else:
  2219. dialog.destroy()
  2220. def _screenshot_grab(self, entire_screen):
  2221. root_win = gtk.gdk.get_default_root_window()
  2222. if entire_screen:
  2223. x = 0
  2224. y = 0
  2225. width = gtk.gdk.screen_width()
  2226. height = gtk.gdk.screen_height()
  2227. else:
  2228. (x, y, width, height) = xmouse.geometry()
  2229. pix = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, width, height)
  2230. pix = pix.get_from_drawable(root_win, gtk.gdk.colormap_get_system(), x, y, 0, 0, width, height)
  2231. # Save as /tmp/mirage-<random>/filename.ext
  2232. tmpdir = tempfile.mkdtemp(prefix="mirage-") + "/"
  2233. tmpfile = tmpdir + "screenshot.png"
  2234. pix.save(tmpfile, 'png')
  2235. # Load file:
  2236. self.image_list = [tmpfile]
  2237. self.curr_img_in_list = 0
  2238. gobject.idle_add(self.load_new_image2, False, False, False, False, True)
  2239. self.update_statusbar()
  2240. self.set_go_navigation_sensitivities(False)
  2241. self.set_slideshow_sensitivities()
  2242. self.thumbpane_update_images(True, self.curr_img_in_list)
  2243. del pix
  2244. self.window.present()
  2245. def show_properties(self, action):
  2246. show_props = gtk.Dialog(_("Properties"), self.window)
  2247. show_props.set_has_separator(False)
  2248. show_props.set_resizable(False)
  2249. table = gtk.Table(3, 3, False)
  2250. image = gtk.Image()
  2251. animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
  2252. image_is_anim = False
  2253. if animtest.is_static_image():
  2254. pixbuf, image_width, image_height = self.get_pixbuf_of_size(self.currimg_pixbuf_original, 180, self.zoom_quality)
  2255. else:
  2256. pixbuf, image_width, image_height = self.get_pixbuf_of_size(animtest.get_static_image(), 180, self.zoom_quality)
  2257. image_is_anim = True
  2258. image.set_from_pixbuf(self.pixbuf_add_border(pixbuf))
  2259. vbox_left = gtk.VBox()
  2260. filename = gtk.Label(_("Dosya Adı:"))
  2261. filename.set_alignment(1, 1)
  2262. filedate = gtk.Label(_("File modified:"))
  2263. filedate.set_alignment(1, 1)
  2264. imagesize = gtk.Label(_("Dimensions:"))
  2265. imagesize.set_alignment(1, 1)
  2266. filesize = gtk.Label(_("File size:"))
  2267. filesize.set_alignment(1, 1)
  2268. filetype = gtk.Label(_("File type:"))
  2269. filetype.set_alignment(1, 1)
  2270. transparency = gtk.Label(_("Saydamlık:"))
  2271. transparency.set_alignment(1, 1)
  2272. animation = gtk.Label(_("Animation:"))
  2273. animation.set_alignment(1, 1)
  2274. bits = gtk.Label(_("Bits per sample:"))
  2275. bits.set_alignment(1, 1)
  2276. channels = gtk.Label(_("Channels:"))
  2277. channels.set_alignment(1, 1)
  2278. vbox_left.pack_start(filename, False, False, 2)
  2279. vbox_left.pack_start(filedate, False, False, 2)
  2280. vbox_left.pack_start(imagesize, False, False, 2)
  2281. vbox_left.pack_start(filesize, False, False, 2)
  2282. vbox_left.pack_start(filetype, False, False, 2)
  2283. vbox_left.pack_start(transparency, False, False, 2)
  2284. vbox_left.pack_start(animation, False, False, 2)
  2285. vbox_left.pack_start(bits, False, False, 2)
  2286. vbox_left.pack_start(channels, False, False, 2)
  2287. vbox_right = gtk.VBox()
  2288. filestat = os.stat(self.currimg_name)
  2289. filename2 = gtk.Label(os.path.basename(self.currimg_name))
  2290. filedate2 = gtk.Label(time.strftime('%c', time.localtime(filestat[stat.ST_MTIME])))
  2291. imagesize2 = gtk.Label(str(self.currimg_pixbuf_original.get_width()) + "x" + str(self.currimg_pixbuf_original.get_height()))
  2292. filetype2 = gtk.Label(gtk.gdk.pixbuf_get_file_info(self.currimg_name)[0]['mime_types'][0])
  2293. filesize2 = gtk.Label(str(filestat[stat.ST_SIZE]/1000) + "KB")
  2294. if not image_is_anim and pixbuf.get_has_alpha():
  2295. transparency2 = gtk.Label(_("Yes"))
  2296. else:
  2297. transparency2 = gtk.Label(_("No"))
  2298. if animtest.is_static_image():
  2299. animation2 = gtk.Label(_("No"))
  2300. else:
  2301. animation2 = gtk.Label(_("Yes"))
  2302. bits2 = gtk.Label(str(pixbuf.get_bits_per_sample()))
  2303. channels2 = gtk.Label(str(pixbuf.get_n_channels()))
  2304. filename2.set_alignment(0, 1)
  2305. filedate2.set_alignment(0, 1)
  2306. imagesize2.set_alignment(0, 1)
  2307. filesize2.set_alignment(0, 1)
  2308. filetype2.set_alignment(0, 1)
  2309. transparency2.set_alignment(0, 1)
  2310. animation2.set_alignment(0, 1)
  2311. bits2.set_alignment(0, 1)
  2312. channels2.set_alignment(0, 1)
  2313. vbox_right.pack_start(filename2, False, False, 2)
  2314. vbox_right.pack_start(filedate2, False, False, 2)
  2315. vbox_right.pack_start(imagesize2, False, False, 2)
  2316. vbox_right.pack_start(filesize2, False, False, 2)
  2317. vbox_right.pack_start(filetype2, False, False, 2)
  2318. vbox_right.pack_start(transparency2, False, False, 2)
  2319. vbox_right.pack_start(animation2, False, False, 2)
  2320. vbox_right.pack_start(bits2, False, False, 2)
  2321. vbox_right.pack_start(channels2, False, False, 2)
  2322. hbox = gtk.HBox()
  2323. hbox.pack_start(vbox_left, False, False, 3)
  2324. hbox.pack_start(vbox_right, False, False, 3)
  2325. table.attach(image, 1, 2, 1, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  2326. table.attach(hbox, 2, 3, 1, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  2327. show_props.vbox.pack_start(table, False, False, 15)
  2328. show_props.vbox.show_all()
  2329. close_button = show_props.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
  2330. close_button.grab_focus()
  2331. show_props.run()
  2332. show_props.destroy()
  2333. def show_prefs(self, action):
  2334. prev_thumbnail_size = self.thumbnail_size
  2335. self.prefs_dialog = gtk.Dialog(_("Mirage Seçenekleri"), self.window)
  2336. self.prefs_dialog.set_has_separator(False)
  2337. self.prefs_dialog.set_resizable(False)
  2338. # "Interface" prefs:
  2339. table_settings = gtk.Table(14, 3, False)
  2340. bglabel = gtk.Label()
  2341. bglabel.set_markup('<b>' + _('Arayüz') + '</b>')
  2342. bglabel.set_alignment(0, 1)
  2343. color_hbox = gtk.HBox(False, 0)
  2344. colortext = gtk.Label(_('Arkaplan Rengi:'))
  2345. self.colorbutton = gtk.ColorButton(self.bgcolor)
  2346. self.colorbutton.connect('color-set', self.bgcolor_selected)
  2347. self.colorbutton.set_size_request(150, -1)
  2348. self.colorbutton.set_tooltip_text(_("Uygulama için arkaplan rengini ayarlar."))
  2349. color_hbox.pack_start(colortext, False, False, 0)
  2350. color_hbox.pack_start(self.colorbutton, False, False, 0)
  2351. color_hbox.pack_start(gtk.Label(), True, True, 0)
  2352. simplecolor_hbox = gtk.HBox(False, 0)
  2353. simplecolortext = gtk.Label(_('Basit arka plan rengi:'))
  2354. simplecolorbutton = gtk.CheckButton()
  2355. simplecolorbutton.connect('toggled', self.simple_bgcolor_selected)
  2356. simplecolor_hbox.pack_start(simplecolortext, False, False, 0)
  2357. simplecolor_hbox.pack_start(simplecolorbutton, False, False, 0)
  2358. simplecolor_hbox.pack_start(gtk.Label(), True, True, 0)
  2359. if self.simple_bgcolor:
  2360. simplecolorbutton.set_active(True)
  2361. fullscreen = gtk.CheckButton(_("Mirage'ı tam ekran modunda aç"))
  2362. fullscreen.set_active(self.start_in_fullscreen)
  2363. thumbbox = gtk.HBox()
  2364. thumblabel = gtk.Label(_("Küçük resim boyutu:"))
  2365. thumbbox.pack_start(thumblabel, False, False, 0)
  2366. thumbsize = gtk.combo_box_new_text()
  2367. option = 0
  2368. for size in self.thumbnail_sizes:
  2369. thumbsize.append_text(size + " x " + size)
  2370. if self.thumbnail_size == int(size):
  2371. thumbsize.set_active(option)
  2372. option += 1
  2373. thumbbox.pack_start(thumbsize, False, False, 5)
  2374. table_settings.attach(gtk.Label(), 1, 3, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2375. table_settings.attach(bglabel, 1, 3, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  2376. table_settings.attach(gtk.Label(), 1, 3, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2377. table_settings.attach(simplecolor_hbox, 1, 2, 4, 5, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2378. table_settings.attach(color_hbox, 1, 2, 5, 6, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2379. table_settings.attach(gtk.Label(), 1, 3, 6, 7, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2380. table_settings.attach(thumbbox, 1, 3, 7, 8, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2381. table_settings.attach(gtk.Label(), 1, 3, 8, 9, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2382. table_settings.attach(fullscreen, 1, 3, 9, 10, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2383. table_settings.attach(gtk.Label(), 1, 3, 10, 11, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2384. table_settings.attach(gtk.Label(), 1, 3, 11, 12, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2385. table_settings.attach(gtk.Label(), 1, 3, 12, 13, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2386. table_settings.attach(gtk.Label(), 1, 3, 13, 14, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2387. table_settings.attach(gtk.Label(), 1, 3, 14, 15, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2388. # "Behavior" tab:
  2389. table_behavior = gtk.Table(14, 2, False)
  2390. openlabel = gtk.Label()
  2391. openlabel.set_markup('<b>' + _('Davranışı aç') + '</b>')
  2392. openlabel.set_alignment(0, 1)
  2393. hbox_openmode = gtk.HBox()
  2394. hbox_openmode.pack_start(gtk.Label(_('Yeni Resim Aç:')), False, False, 0)
  2395. combobox = gtk.combo_box_new_text()
  2396. combobox.append_text(_("Akıllı Mod"))
  2397. combobox.append_text(_("Uygun Boyut Modu"))
  2398. combobox.append_text(_("1:1 Mod"))
  2399. combobox.append_text(_("Son Aktif Mod"))
  2400. combobox.set_active(self.open_mode)
  2401. hbox_openmode.pack_start(combobox, False, False, 5)
  2402. openallimages = gtk.CheckButton(_("Tüm resimleri geçerli dizine yükle"))
  2403. openallimages.set_active(self.open_all_images)
  2404. openallimages.set_tooltip_text(_("Etkinleştirilirse, Mirage'da bir görüntü açınca, o görüntü dizininde bulunan tüm görüntüleri otomatik olarak yükler."))
  2405. hiddenimages = gtk.CheckButton(_("Gizli dosyaları yüklemeye izin ver"))
  2406. hiddenimages.set_active(self.open_hidden_files)
  2407. hiddenimages.set_tooltip_text(_("İşaretlenirse, Mirage gizli dosyaları açacaktır. Aksi halde, gizli dosyalar göz ardı edilir."))
  2408. openpref = gtk.RadioButton()
  2409. openpref1 = gtk.RadioButton(group=openpref, label=_("Son seçilen dizini kullan"))
  2410. openpref1.set_tooltip_text(_("Varsayılan 'Open' dizini kullanılan son dizin olacaktır."))
  2411. openpref2 = gtk.RadioButton(group=openpref, label=_("Bu sabit dizini kullan:"))
  2412. openpref2.connect('toggled', self.prefs_use_fixed_dir_clicked)
  2413. openpref2.set_tooltip_text(_("Varsayılan 'Açık' dizin belirtilen dizin olacaktır."))
  2414. hbox_defaultdir = gtk.HBox()
  2415. self.defaultdir = gtk.Button()
  2416. hbox_defaultdir.pack_start(gtk.Label(), True, True, 0)
  2417. hbox_defaultdir.pack_start(self.defaultdir, False, False, 0)
  2418. hbox_defaultdir.pack_start(gtk.Label(), True, True, 0)
  2419. if len(self.fixed_dir) > 25:
  2420. self.defaultdir.set_label('...' + self.fixed_dir[-22:])
  2421. else:
  2422. self.defaultdir.set_label(self.fixed_dir)
  2423. self.defaultdir.connect('clicked', self.defaultdir_clicked)
  2424. self.defaultdir.set_size_request(250, -1)
  2425. if self.use_last_dir:
  2426. openpref1.set_active(True)
  2427. self.defaultdir.set_sensitive(False)
  2428. else:
  2429. openpref2.set_active(True)
  2430. self.defaultdir.set_sensitive(True)
  2431. table_behavior.attach(gtk.Label(), 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2432. table_behavior.attach(openlabel, 1, 2, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  2433. table_behavior.attach(gtk.Label(), 1, 2, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2434. table_behavior.attach(hbox_openmode, 1, 2, 4, 5, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2435. table_behavior.attach(gtk.Label(), 1, 2, 5, 6, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2436. table_behavior.attach(openallimages, 1, 2, 6, 7, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2437. table_behavior.attach(hiddenimages, 1, 2, 7, 8, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2438. table_behavior.attach(gtk.Label(), 1, 2, 8, 9, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2439. table_behavior.attach(openpref1, 1, 2, 9, 10, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2440. table_behavior.attach(openpref2, 1, 2, 10, 11, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2441. table_behavior.attach(hbox_defaultdir, 1, 2, 11, 12, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 45, 0)
  2442. table_behavior.attach(gtk.Label(), 1, 2, 12, 13, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 45, 0)
  2443. # "Navigation" tab:
  2444. table_navigation = gtk.Table(14, 2, False)
  2445. navlabel = gtk.Label()
  2446. navlabel.set_markup('<b>' + _('Gezinme') + '</b>')
  2447. navlabel.set_alignment(0, 1)
  2448. preloadnav = gtk.CheckButton(label=_("Daha hızlı gezinme için görüntüleri önceden yükleyin"))
  2449. preloadnav.set_active(self.preloading_images)
  2450. preloadnav.set_tooltip_text(_("Etkinleştirilirse, listedeki sonraki ve önceki görüntüler boşta kalma süresi boyunca önceden yüklenir. Hız artışının bellek kullanımı pahasına olduğunu unutmayın, bu nedenle bu seçeneği sınırlı ram olan makinelerde devre dışı bırakmanız önerilir."))
  2451. hbox_listwrap = gtk.HBox()
  2452. hbox_listwrap.pack_start(gtk.Label(_("Görselin etrafına sar:")), False, False, 0)
  2453. combobox2 = gtk.combo_box_new_text()
  2454. combobox2.append_text(_("Hayır"))
  2455. combobox2.append_text(_("Evet"))
  2456. combobox2.append_text(_("Prompt User"))
  2457. combobox2.set_active(self.listwrap_mode)
  2458. hbox_listwrap.pack_start(combobox2, False, False, 5)
  2459. table_navigation.attach(gtk.Label(), 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2460. table_navigation.attach(navlabel, 1, 2, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  2461. table_navigation.attach(gtk.Label(), 1, 2, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2462. table_navigation.attach(hbox_listwrap, 1, 2, 4, 5, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2463. table_navigation.attach(gtk.Label(), 1, 2, 5, 6, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2464. table_navigation.attach(preloadnav, 1, 2, 6, 7, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2465. table_navigation.attach(gtk.Label(), 1, 2, 7, 8, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2466. table_navigation.attach(gtk.Label(), 1, 2, 8, 9, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2467. table_navigation.attach(gtk.Label(), 1, 2, 9, 10, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2468. table_navigation.attach(gtk.Label(), 1, 2, 10, 11, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2469. table_navigation.attach(gtk.Label(), 1, 2, 11, 12, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2470. table_navigation.attach(gtk.Label(), 1, 2, 12, 13, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2471. table_navigation.attach(gtk.Label(), 1, 2, 13, 14, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2472. # "Slideshow" tab:
  2473. table_slideshow = gtk.Table(14, 2, False)
  2474. slideshowlabel = gtk.Label()
  2475. slideshowlabel.set_markup('<b>' + _('Slayt Gösterisi Modu') + '</b>')
  2476. slideshowlabel.set_alignment(0, 1)
  2477. hbox_delay = gtk.HBox()
  2478. hbox_delay.pack_start(gtk.Label(_("Saniyede resimler arasında gecikme:")), False, False, 0)
  2479. spin_adj = gtk.Adjustment(self.slideshow_delay, 0, 50000, 1, 10, 0)
  2480. delayspin = gtk.SpinButton(spin_adj, 1.0, 0)
  2481. delayspin.set_numeric(True)
  2482. hbox_delay.pack_start(delayspin, False, False, 5)
  2483. randomize = gtk.CheckButton(_("Görüntülerin sırasını sırala"))
  2484. randomize.set_active(self.slideshow_random)
  2485. randomize.set_tooltip_text(_("Etkinleştirildiğinde, slayt gösterisi sırasında rastgele bir resim seçilecektir (herhangi bir görüntüyü iki kez yüklemeden)."))
  2486. disable_screensaver = gtk.CheckButton(_("Slayt gösterisi modunda ekran koruyucuyu devre dışı bırak"))
  2487. disable_screensaver.set_active(self.disable_screensaver)
  2488. disable_screensaver.set_tooltip_text(_("If enabled, xscreensaver will be temporarily disabled during slideshow mode."))
  2489. ss_in_fs = gtk.CheckButton(_("Her zaman tam ekran modunda başlat"))
  2490. ss_in_fs.set_tooltip_text(_("Etkinleştirildiğinde, bir slayt gösterisi başlatılması uygulamayı tam ekran moduna geçirir."))
  2491. ss_in_fs.set_active(self.slideshow_in_fullscreen)
  2492. table_slideshow.attach(gtk.Label(), 1, 2, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2493. table_slideshow.attach(slideshowlabel, 1, 2, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  2494. table_slideshow.attach(gtk.Label(), 1, 2, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2495. table_slideshow.attach(hbox_delay, 1, 2, 4, 5, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2496. table_slideshow.attach(gtk.Label(), 1, 2, 5, 6, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2497. table_slideshow.attach(disable_screensaver, 1, 2, 6, 7, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2498. table_slideshow.attach(ss_in_fs, 1, 2, 7, 8, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2499. table_slideshow.attach(randomize, 1, 2, 8, 9, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2500. table_slideshow.attach(gtk.Label(), 1, 2, 9, 10, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2501. table_slideshow.attach(gtk.Label(), 1, 2, 10, 11, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2502. table_slideshow.attach(gtk.Label(), 1, 2, 11, 12, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2503. table_slideshow.attach(gtk.Label(), 1, 2, 12, 13, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2504. table_slideshow.attach(gtk.Label(), 1, 2, 13, 14, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 0, 0)
  2505. # "Image" tab:
  2506. table_image = gtk.Table(14, 2, False)
  2507. imagelabel = gtk.Label()
  2508. imagelabel.set_markup('<b>' + _('Resim Düzenleme') + '</b>')
  2509. imagelabel.set_alignment(0, 1)
  2510. deletebutton = gtk.CheckButton(_("Resim silmeyi onayla"))
  2511. deletebutton.set_active(self.confirm_delete)
  2512. zoom_hbox = gtk.HBox()
  2513. zoom_hbox.pack_start(gtk.Label(_('Ölçekleme kalitesi:')), False, False, 0)
  2514. zoomcombo = gtk.combo_box_new_text()
  2515. zoomcombo.append_text(_("Nearest (Fastest)"))
  2516. zoomcombo.append_text(_("Tiles"))
  2517. zoomcombo.append_text(_("Bilinear"))
  2518. zoomcombo.append_text(_("Hyper (Best)"))
  2519. zoomcombo.set_active(self.zoomvalue)
  2520. zoom_hbox.pack_start(zoomcombo, False, False, 0)
  2521. zoom_hbox.pack_start(gtk.Label(), True, True, 0)
  2522. hbox_save = gtk.HBox()
  2523. savelabel = gtk.Label(_("Modified images:"))
  2524. savecombo = gtk.combo_box_new_text()
  2525. savecombo.append_text(_("Ignore Changes"))
  2526. savecombo.append_text(_("Oto-Kaydet"))
  2527. savecombo.append_text(_("Prompt For Action"))
  2528. savecombo.set_active(self.savemode)
  2529. hbox_save.pack_start(savelabel, False, False, 0)
  2530. hbox_save.pack_start(savecombo, False, False, 5)
  2531. hbox_quality = gtk.HBox()
  2532. qualitylabel = gtk.Label(_("Quality to save in:"))
  2533. qspin_adj = gtk.Adjustment(self.quality_save, 0, 100, 1, 100, 0)
  2534. qualityspin = gtk.SpinButton(qspin_adj, 1.0, 0)
  2535. qualityspin.set_numeric(True)
  2536. hbox_quality.pack_start(qualitylabel, False, False, 0)
  2537. hbox_quality.pack_start(qualityspin, False, False, 5)
  2538. table_image.attach(gtk.Label(), 1, 3, 1, 2, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2539. table_image.attach(imagelabel, 1, 3, 2, 3, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 15, 0)
  2540. table_image.attach(gtk.Label(), 1, 3, 3, 4, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2541. table_image.attach(zoom_hbox, 1, 3, 4, 5, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2542. table_image.attach(gtk.Label(), 1, 3, 5, 6, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2543. table_image.attach(hbox_save, 1, 3, 6, 7, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2544. table_image.attach(gtk.Label(), 1, 3, 7, 8, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2545. table_image.attach(hbox_quality, 1, 3, 8, 9, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2546. table_image.attach(gtk.Label(), 1, 3, 9, 10, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2547. table_image.attach(deletebutton, 1, 3, 10, 11, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2548. table_image.attach(gtk.Label(), 1, 3, 11, 12, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2549. table_image.attach(gtk.Label(), 1, 3, 12, 13, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2550. table_image.attach(gtk.Label(), 1, 3, 13, 14, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2551. table_image.attach(gtk.Label(), 1, 3, 14, 15, gtk.FILL|gtk.EXPAND, gtk.FILL|gtk.EXPAND, 30, 0)
  2552. # Add tabs:
  2553. notebook = gtk.Notebook()
  2554. notebook.append_page(table_behavior, gtk.Label(_("Davranış")))
  2555. notebook.append_page(table_navigation, gtk.Label(_("Gezinti")))
  2556. notebook.append_page(table_settings, gtk.Label(_("Arayüz")))
  2557. notebook.append_page(table_slideshow, gtk.Label(_("Slayt Görüntüsü")))
  2558. notebook.append_page(table_image, gtk.Label(_("Resim")))
  2559. notebook.set_current_page(0)
  2560. hbox = gtk.HBox()
  2561. self.prefs_dialog.vbox.pack_start(hbox, False, False, 7)
  2562. hbox.pack_start(notebook, False, False, 7)
  2563. notebook.connect('switch-page', self.prefs_tab_switched)
  2564. # Show prefs:
  2565. self.prefs_dialog.vbox.show_all()
  2566. self.close_button = self.prefs_dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
  2567. self.close_button.grab_focus()
  2568. response = self.prefs_dialog.run()
  2569. if response == gtk.RESPONSE_CLOSE or response == gtk.RESPONSE_DELETE_EVENT:
  2570. self.zoomvalue = zoomcombo.get_active()
  2571. if int(round(self.zoomvalue, 0)) == 0:
  2572. self.zoom_quality = gtk.gdk.INTERP_NEAREST
  2573. elif int(round(self.zoomvalue, 0)) == 1:
  2574. self.zoom_quality = gtk.gdk.INTERP_TILES
  2575. elif int(round(self.zoomvalue, 0)) == 2:
  2576. self.zoom_quality = gtk.gdk.INTERP_BILINEAR
  2577. elif int(round(self.zoomvalue, 0)) == 3:
  2578. self.zoom_quality = gtk.gdk.INTERP_HYPER
  2579. self.open_all_images = openallimages.get_active()
  2580. self.open_hidden_files = hiddenimages.get_active()
  2581. if openpref1.get_active():
  2582. self.use_last_dir = True
  2583. else:
  2584. self.use_last_dir = False
  2585. open_mode_prev = self.open_mode
  2586. self.open_mode = combobox.get_active()
  2587. preloading_images_prev = self.preloading_images
  2588. self.preloading_images = preloadnav.get_active()
  2589. self.listwrap_mode = combobox2.get_active()
  2590. self.slideshow_delay = delayspin.get_value()
  2591. self.curr_slideshow_delay = self.slideshow_delay
  2592. self.slideshow_random = randomize.get_active()
  2593. self.curr_slideshow_random = self.slideshow_random
  2594. self.disable_screensaver = disable_screensaver.get_active()
  2595. self.slideshow_in_fullscreen = ss_in_fs.get_active()
  2596. self.savemode = savecombo.get_active()
  2597. self.start_in_fullscreen = fullscreen.get_active()
  2598. self.confirm_delete = deletebutton.get_active()
  2599. self.quality_save = qualityspin.get_value()
  2600. self.thumbnail_size = int(self.thumbnail_sizes[thumbsize.get_active()])
  2601. if self.thumbnail_size != prev_thumbnail_size:
  2602. gobject.idle_add(self.thumbpane_set_size)
  2603. gobject.idle_add(self.thumbpane_update_images, True, self.curr_img_in_list)
  2604. self.prefs_dialog.destroy()
  2605. self.set_go_navigation_sensitivities(False)
  2606. if (self.preloading_images and not preloading_images_prev) or (open_mode_prev != self.open_mode):
  2607. # The user just turned on preloading, so do it:
  2608. self.preloadimg_next_in_list = -1
  2609. self.preloadimg_prev_in_list = -1
  2610. self.preload_when_idle = gobject.idle_add(self.preload_next_image, False)
  2611. self.preload_when_idle2 = gobject.idle_add(self.preload_prev_image, False)
  2612. elif not self.preloading_images:
  2613. self.preloadimg_next_in_list = -1
  2614. self.preloadimg_prev_in_list = -1
  2615. def prefs_use_fixed_dir_clicked(self, button):
  2616. if button.get_active():
  2617. self.defaultdir.set_sensitive(True)
  2618. else:
  2619. self.defaultdir.set_sensitive(False)
  2620. def rename_image(self, action):
  2621. if len(self.image_list) > 0:
  2622. temp_slideshow_mode = self.slideshow_mode
  2623. if self.slideshow_mode:
  2624. self.toggle_slideshow(None)
  2625. rename_dialog = gtk.Dialog(_('Resmi Yeniden Adlandır'), self.window, gtk.DIALOG_MODAL)
  2626. self.rename_txt = gtk.Entry()
  2627. filename = os.path.basename(self.currimg_name)
  2628. self.rename_txt.set_text(filename)
  2629. self.rename_txt.set_activates_default(True)
  2630. cancelbutton = rename_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
  2631. renamebutton = rename_dialog.add_button(_("_Yeniden Adlandır"), gtk.RESPONSE_ACCEPT)
  2632. renameimage = gtk.Image()
  2633. renameimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
  2634. renamebutton.set_image(renameimage)
  2635. animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
  2636. if animtest.is_static_image():
  2637. pixbuf, image_width, image_height = self.get_pixbuf_of_size(self.currimg_pixbuf_original, 60, self.zoom_quality)
  2638. else:
  2639. pixbuf, image_width, image_height = self.get_pixbuf_of_size(animtest.get_static_image(), 60, self.zoom_quality)
  2640. image = gtk.Image()
  2641. image.set_from_pixbuf(pixbuf)
  2642. instructions = gtk.Label(_("Yeni adı giriniz:"))
  2643. instructions.set_alignment(0, 1)
  2644. hbox = gtk.HBox()
  2645. hbox.pack_start(image, False, False, 10)
  2646. vbox_stuff = gtk.VBox()
  2647. vbox_stuff.pack_start(gtk.Label(), False, False, 0)
  2648. vbox_stuff.pack_start(instructions, False, False, 0)
  2649. vbox_stuff.pack_start(gtk.Label(), False, False, 0)
  2650. vbox_stuff.pack_start(self.rename_txt, True, True, 0)
  2651. vbox_stuff.pack_start(gtk.Label(), False, False, 0)
  2652. hbox.pack_start(vbox_stuff, True, True, 10)
  2653. rename_dialog.vbox.pack_start(hbox, False, False, 0)
  2654. rename_dialog.set_has_separator(True)
  2655. rename_dialog.set_default_response(gtk.RESPONSE_ACCEPT)
  2656. rename_dialog.set_size_request(300, -1)
  2657. rename_dialog.vbox.show_all()
  2658. rename_dialog.connect('show', self.select_rename_text)
  2659. response = rename_dialog.run()
  2660. if response == gtk.RESPONSE_ACCEPT:
  2661. try:
  2662. new_filename = os.path.dirname(self.currimg_name) + "/" + self.rename_txt.get_text()
  2663. shutil.move(self.currimg_name, new_filename)
  2664. # Update thumbnail filename:
  2665. try:
  2666. shutil.move(self_get_name(self.currimg_name)[1], self.thumbnail_get_name(new_filename)[1])
  2667. except:
  2668. pass
  2669. self.recent_file_remove_and_refresh_name(self.currimg_name)
  2670. self.currimg_name = new_filename
  2671. self.register_file_with_recent_docs(self.currimg_name)
  2672. self.update_title()
  2673. except:
  2674. error_dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, _('%s yeniden adlandırılamıyor') % self.currimg_name)
  2675. error_dialog.set_title(_("Yeniden adlandırılamıyor"))
  2676. error_dialog.run()
  2677. error_dialog.destroy()
  2678. rename_dialog.destroy()
  2679. if temp_slideshow_mode:
  2680. self.toggle_slideshow(None)
  2681. def select_rename_text(self, widget):
  2682. filename = os.path.basename(self.currimg_name)
  2683. fileext = os.path.splitext(os.path.basename(self.currimg_name))[1]
  2684. self.rename_txt.select_region(0, len(filename) - len(fileext))
  2685. def delete_image(self, action):
  2686. if len(self.image_list) > 0:
  2687. temp_slideshow_mode = self.slideshow_mode
  2688. if self.slideshow_mode:
  2689. self.toggle_slideshow(None)
  2690. delete_dialog = gtk.Dialog(_('Resmi Sil'), self.window, gtk.DIALOG_MODAL)
  2691. if self.confirm_delete:
  2692. permlabel = gtk.Label(_('%s kalıcı olarak silinecek onaylıyor musunuz??') % os.path.split(self.currimg_name)[1])
  2693. permlabel.set_line_wrap(True)
  2694. permlabel.set_alignment(0, 0.1)
  2695. warningicon = gtk.Image()
  2696. warningicon.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG)
  2697. hbox = gtk.HBox()
  2698. hbox.pack_start(warningicon, False, False, 10)
  2699. hbox.pack_start(permlabel, False, False, 10)
  2700. delete_dialog.vbox.pack_start(gtk.Label(), False, False, 0)
  2701. delete_dialog.vbox.pack_start(hbox, False, False, 0)
  2702. cancelbutton = delete_dialog.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
  2703. deletebutton = delete_dialog.add_button(gtk.STOCK_DELETE, gtk.RESPONSE_YES)
  2704. delete_dialog.set_has_separator(False)
  2705. deletebutton.set_property('has-focus', True)
  2706. delete_dialog.set_default_response(gtk.RESPONSE_YES)
  2707. delete_dialog.vbox.show_all()
  2708. response = delete_dialog.run()
  2709. else:
  2710. response = gtk.RESPONSE_YES
  2711. if response == gtk.RESPONSE_YES:
  2712. try:
  2713. os.remove(self.currimg_name)
  2714. self.image_modified = False
  2715. try:
  2716. os.remove(self.thumbnail_get_name(self.currimg_name)[1])
  2717. except:
  2718. pass
  2719. self.recent_file_remove_and_refresh_name(self.currimg_name)
  2720. iter = self.thumblist.get_iter((self.curr_img_in_list,))
  2721. try:
  2722. self.thumbnail_loaded.pop(self.curr_img_in_list)
  2723. self.thumbpane_update_images()
  2724. except:
  2725. pass
  2726. self.thumblist.remove(iter)
  2727. templist = self.image_list
  2728. self.image_list = []
  2729. for item in templist:
  2730. if item != self.currimg_name:
  2731. self.image_list.append(item)
  2732. if len(self.image_list) >= 1:
  2733. if len(self.image_list) == 1:
  2734. self.curr_img_in_list = 0
  2735. elif self.curr_img_in_list == len(self.image_list):
  2736. self.curr_img_in_list -= 1
  2737. self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
  2738. self.preloadimg_prev_in_list = -1
  2739. self.preloadimg_next_in_list = -1
  2740. self.load_when_idle = gobject.idle_add(self.load_new_image, False, False, True, True, True, True)
  2741. self.set_go_navigation_sensitivities(False)
  2742. else:
  2743. self.imageview.clear()
  2744. self.update_title()
  2745. self.statusbar.push(self.statusbar.get_context_id(""), "")
  2746. self.image_loaded = False
  2747. self.set_slideshow_sensitivities()
  2748. self.set_image_sensitivities(False)
  2749. self.set_go_navigation_sensitivities(False)
  2750. # Select new item:
  2751. self.thumbpane_select(self.curr_img_in_list)
  2752. except:
  2753. error_dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, _('%s silinemedi') % self.currimg_name)
  2754. error_dialog.set_title(_("Silinemedi"))
  2755. error_dialog.run()
  2756. error_dialog.destroy()
  2757. delete_dialog.destroy()
  2758. if temp_slideshow_mode:
  2759. self.toggle_slideshow(None)
  2760. def defaultdir_clicked(self, button):
  2761. getdir = gtk.FileChooserDialog(title=_("Dizin Seçimi"),action=gtk.FILE_CHOOSER_ACTION_OPEN,buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
  2762. getdir.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
  2763. getdir.set_filename(self.fixed_dir)
  2764. getdir.set_default_response(gtk.RESPONSE_OK)
  2765. response = getdir.run()
  2766. if response == gtk.RESPONSE_OK:
  2767. self.fixed_dir = getdir.get_filenames()[0]
  2768. if len(self.fixed_dir) > 25:
  2769. button.set_label('...' + self.fixed_dir[-22:])
  2770. else:
  2771. button.set_label(self.fixed_dir)
  2772. getdir.destroy()
  2773. else:
  2774. getdir.destroy()
  2775. def prefs_tab_switched(self, notebook, page, page_num):
  2776. do_when_idle = gobject.idle_add(self.grab_close_button)
  2777. def grab_close_button(self):
  2778. self.close_button.grab_focus()
  2779. def bgcolor_selected(self, widget):
  2780. # When the user selects a color, store this color in self.bgcolor (which will
  2781. # later be saved to .miragerc) and set this background color:
  2782. self.bgcolor = widget.get_property('color')
  2783. if not self.simple_bgcolor:
  2784. self.layout.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
  2785. self.slideshow_window.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
  2786. self.slideshow_window2.modify_bg(gtk.STATE_NORMAL, self.bgcolor)
  2787. def simple_bgcolor_selected(self, widget):
  2788. if widget.get_active():
  2789. self.simple_bgcolor = True
  2790. self.layout.modify_bg(gtk.STATE_NORMAL, None)
  2791. else:
  2792. self.simple_bgcolor = False
  2793. self.bgcolor_selected(self.colorbutton)
  2794. def show_about(self, action):
  2795. # Help > About
  2796. self.about_dialog = gtk.AboutDialog()
  2797. try:
  2798. self.about_dialog.set_transient_for(self.window)
  2799. self.about_dialog.set_modal(True)
  2800. except:
  2801. pass
  2802. self.about_dialog.set_name('Mirage')
  2803. self.about_dialog.set_version(__version__)
  2804. self.about_dialog.set_comments(_('Hızlı Resim Görüntüleyici.\nTürkçe Çeviri: Cihan Alkan'))
  2805. self.about_dialog.set_license(__license__)
  2806. self.about_dialog.set_authors(['Scott Horowitz <stonecrest@gmail.com>', 'Fredric Johansson <fredric.miscmail@gmail.com>'])
  2807. self.about_dialog.set_artists(['William Rea <sillywilly@gmail.com>'])
  2808. self.about_dialog.set_translator_credits('Türkçe - Cihan Alkan <cihanalk@gmail.com>\nSlovakça - Petr Pisar <petr.pisar@atlas.cz>\nAlmanca - Bjoern Martensen <bjoern.martensen@gmail.com>\nİspanyolca - Isidro Arribas <cdhotfire@gmail.com>\nFransızca - Mike Massonnet <mmassonnet@gmail.com>\nMacarca - Sandor Lisovszki <lisovszki@dunakanyar.net>\nFlemenkçe - Pascal De Vuyst <pascal.devuyst@gmail.com>\nLehçe - Tomasz Dominikowski <dominikowski@gmail.com>\nPortekizce - Danilo Martins <mawkee@gmail.com>\nRusça - mavka <mavka@justos.org>\nİtalyanca - Daniele Maggio <dado84@freemail.it>\nÇince - Jayden Suen <no.sun@163.com>')
  2809. gtk.about_dialog_set_url_hook(self.show_website, "http://mirageiv.berlios.de")
  2810. self.about_dialog.set_website_label("http://mirageiv.berlios.de")
  2811. icon_path = self.find_path('mirage.png')
  2812. try:
  2813. icon_pixbuf = gtk.gdk.pixbuf_new_from_file(icon_path)
  2814. self.about_dialog.set_logo(icon_pixbuf)
  2815. except:
  2816. pass
  2817. self.about_dialog.connect('response', self.close_about)
  2818. self.about_dialog.connect('delete_event', self.close_about)
  2819. self.about_dialog.show_all()
  2820. def show_website(self, dialog, blah, link):
  2821. self.browser_load(link)
  2822. def show_help(self, action):
  2823. self.browser_load("http://mirageiv.berlios.de/docs.html")
  2824. def browser_load(self, docslink):
  2825. try:
  2826. pid = subprocess.Popen(["gnome-open", docslink]).pid
  2827. except:
  2828. try:
  2829. pid = subprocess.Popen(["exo-open", docslink]).pid
  2830. except:
  2831. try:
  2832. pid = subprocess.Popen(["kfmclient", "openURL", docslink]).pid
  2833. except:
  2834. try:
  2835. pid = subprocess.Popen(["firefox", docslink]).pid
  2836. except:
  2837. try:
  2838. pid = subprocess.Popen(["mozilla", docslink]).pid
  2839. except:
  2840. try:
  2841. pid = subprocess.Popen(["opera", docslink]).pid
  2842. except:
  2843. error_dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, _('Uygun bir tarayıcı başlatılamıyor.'))
  2844. error_dialog.run()
  2845. error_dialog.destroy()
  2846. def close_about(self, event, data=None):
  2847. self.about_dialog.hide()
  2848. return True
  2849. def mousewheel_scrolled(self, widget, event):
  2850. if event.type == gtk.gdk.SCROLL:
  2851. # Zooming of the image by Ctrl-mousewheel
  2852. if event.state & gtk.gdk.CONTROL_MASK:
  2853. if event.direction == gtk.gdk.SCROLL_UP:
  2854. self.zoom_in(None)
  2855. elif event.direction == gtk.gdk.SCROLL_DOWN:
  2856. self.zoom_out(None)
  2857. return True
  2858. # Navigation of images with mousewheel:
  2859. else:
  2860. if event.direction == gtk.gdk.SCROLL_UP:
  2861. self.goto_prev_image(None)
  2862. elif event.direction == gtk.gdk.SCROLL_DOWN:
  2863. self.goto_next_image(None)
  2864. return True
  2865. def mouse_moved(self, widget, event):
  2866. # This handles the panning of the image
  2867. if event.is_hint:
  2868. x, y, state = event.window.get_pointer()
  2869. else:
  2870. state = event.state
  2871. x, y = event.x_root, event.y_root
  2872. if (state & gtk.gdk.BUTTON2_MASK) or (state & gtk.gdk.BUTTON1_MASK):
  2873. # Prevent self.expose_event() from potentially further changing the
  2874. # adjustments upon the adjustment value changes
  2875. self.updating_adjustments = True
  2876. xadjust = self.layout.get_hadjustment()
  2877. newx = xadjust.value + (self.prevmousex - x)
  2878. if newx >= xadjust.lower and newx <= xadjust.upper - xadjust.page_size:
  2879. xadjust.set_value(newx)
  2880. self.layout.set_hadjustment(xadjust)
  2881. yadjust = self.layout.get_vadjustment()
  2882. newy = yadjust.value + (self.prevmousey - y)
  2883. if newy >= yadjust.lower and newy <= yadjust.upper - yadjust.page_size:
  2884. yadjust.set_value(newy)
  2885. self.layout.set_vadjustment(yadjust)
  2886. self.updating_adjustments = False
  2887. self.prevmousex = x
  2888. self.prevmousey = y
  2889. if self.fullscreen_mode:
  2890. # Show cursor on movement, then hide after 2 seconds of no movement
  2891. self.change_cursor(None)
  2892. if not self.slideshow_controls_visible:
  2893. gobject.source_remove(self.timer_id)
  2894. if not self.closing_app:
  2895. while gtk.events_pending():
  2896. gtk.main_iteration()
  2897. self.timer_id = gobject.timeout_add(2000, self.hide_cursor)
  2898. if y > 0.9*self.available_image_height():
  2899. self.slideshow_controls_show()
  2900. else:
  2901. self.slideshow_controls_hide()
  2902. return True
  2903. def button_pressed(self, widget, event):
  2904. if self.image_loaded:
  2905. # Changes the cursor to the 'resize' cursor, like GIMP, on a middle click:
  2906. if (event.button == 2 or event.button == 1) and (self.hscroll.get_property('visible')==True or self.vscroll.get_property('visible')==True):
  2907. self.change_cursor(gtk.gdk.Cursor(gtk.gdk.FLEUR))
  2908. self.prevmousex = event.x_root
  2909. self.prevmousey = event.y_root
  2910. # Right-click popup:
  2911. elif self.image_loaded and event.button == 3:
  2912. self.UIManager.get_widget('/Popup').popup(None, None, None, event.button, event.time)
  2913. return True
  2914. def button_released(self, widget, event):
  2915. # Resets the cursor when middle mouse button is released
  2916. if event.button == 2 or event.button == 1:
  2917. self.change_cursor(None)
  2918. return True
  2919. def zoom_in(self, action):
  2920. if self.currimg_name != "" and self.UIManager.get_widget('/MainMenu/ViewMenu/In').get_property('sensitive'):
  2921. self.image_zoomed = True
  2922. self.currimg_zoomratio = self.currimg_zoomratio * 1.25
  2923. self.set_zoom_sensitivities()
  2924. self.last_image_action_was_fit = False
  2925. self.put_zoom_image_to_window(False)
  2926. self.update_statusbar()
  2927. def zoom_out(self, action):
  2928. if self.currimg_name != "" and self.UIManager.get_widget('/MainMenu/ViewMenu/Out').get_property('sensitive'):
  2929. if self.currimg_zoomratio == self.min_zoomratio:
  2930. # No point in proceeding..
  2931. return
  2932. self.image_zoomed = True
  2933. self.currimg_zoomratio = self.currimg_zoomratio * 1/1.25
  2934. if self.currimg_zoomratio < self.min_zoomratio:
  2935. self.currimg_zoomratio = self.min_zoomratio
  2936. self.set_zoom_sensitivities()
  2937. self.last_image_action_was_fit = False
  2938. self.put_zoom_image_to_window(False)
  2939. self.update_statusbar()
  2940. def zoom_to_fit_window_action(self, action):
  2941. self.zoom_to_fit_window(action, False, False)
  2942. def zoom_to_fit_window(self, action, is_preloadimg_next, is_preloadimg_prev):
  2943. if is_preloadimg_next:
  2944. if self.preloading_images and self.preloadimg_next_in_list != -1:
  2945. win_width = self.available_image_width()
  2946. win_height = self.available_image_height()
  2947. preimg_width = self.preloadimg_next_pixbuf_original.get_width()
  2948. preimg_height = self.preloadimg_next_pixbuf_original.get_height()
  2949. prewidth_ratio = float(preimg_width)/win_width
  2950. preheight_ratio = float(preimg_height)/win_height
  2951. if prewidth_ratio < preheight_ratio:
  2952. premax_ratio = preheight_ratio
  2953. else:
  2954. premax_ratio = prewidth_ratio
  2955. self.preloadimg_next_zoomratio = 1/float(max_ratio)
  2956. elif is_preloadimg_prev:
  2957. if self.preloading_images and self.preloadimg_prev_in_list != -1:
  2958. win_width = self.available_image_width()
  2959. win_height = self.available_image_height()
  2960. preimg_width = self.preloadimg_prev_pixbuf_original.get_width()
  2961. preimg_height = self.preloadimg_prev_pixbuf_original.get_height()
  2962. prewidth_ratio = float(preimg_width)/win_width
  2963. preheight_ratio = float(preimg_height)/win_height
  2964. if prewidth_ratio < preheight_ratio:
  2965. premax_ratio = preheight_ratio
  2966. else:
  2967. premax_ratio = prewidth_ratio
  2968. self.preloadimg_prev_zoomratio = 1/float(max_ratio)
  2969. else:
  2970. if self.currimg_name != "" and (self.slideshow_mode or self.UIManager.get_widget('/MainMenu/ViewMenu/Fit').get_property('sensitive')):
  2971. self.image_zoomed = True
  2972. self.last_mode = self.open_mode_fit
  2973. self.last_image_action_was_fit = True
  2974. self.last_image_action_was_smart_fit = False
  2975. # Calculate zoomratio needed to fit to window:
  2976. win_width = self.available_image_width()
  2977. win_height = self.available_image_height()
  2978. img_width = self.currimg_pixbuf_original.get_width()
  2979. img_height = self.currimg_pixbuf_original.get_height()
  2980. width_ratio = float(img_width)/win_width
  2981. height_ratio = float(img_height)/win_height
  2982. if width_ratio < height_ratio:
  2983. max_ratio = height_ratio
  2984. else:
  2985. max_ratio = width_ratio
  2986. self.currimg_zoomratio = 1/float(max_ratio)
  2987. self.set_zoom_sensitivities()
  2988. self.put_zoom_image_to_window(False)
  2989. self.update_statusbar()
  2990. def zoom_to_fit_or_1_to_1(self, action, is_preloadimg_next, is_preloadimg_prev):
  2991. if is_preloadimg_next:
  2992. if self.preloading_images and self.preloadimg_next_in_list != -1:
  2993. win_width = self.available_image_width()
  2994. win_height = self.available_image_height()
  2995. preimg_width = self.preloadimg_next_pixbuf_original.get_width()
  2996. preimg_height = self.preloadimg_next_pixbuf_original.get_height()
  2997. prewidth_ratio = float(preimg_width)/win_width
  2998. preheight_ratio = float(preimg_height)/win_height
  2999. if prewidth_ratio < preheight_ratio:
  3000. premax_ratio = preheight_ratio
  3001. else:
  3002. premax_ratio = prewidth_ratio
  3003. self.preloadimg_next_zoomratio = 1/float(premax_ratio)
  3004. if self.preloadimg_next_zoomratio > 1:
  3005. self.preloadimg_next_zoomratio = 1
  3006. elif is_preloadimg_prev:
  3007. if self.preloading_images and self.preloadimg_prev_in_list != -1:
  3008. win_width = self.available_image_width()
  3009. win_height = self.available_image_height()
  3010. preimg_width = self.preloadimg_prev_pixbuf_original.get_width()
  3011. preimg_height = self.preloadimg_prev_pixbuf_original.get_height()
  3012. prewidth_ratio = float(preimg_width)/win_width
  3013. preheight_ratio = float(preimg_height)/win_height
  3014. if prewidth_ratio < preheight_ratio:
  3015. premax_ratio = preheight_ratio
  3016. else:
  3017. premax_ratio = prewidth_ratio
  3018. self.preloadimg_prev_zoomratio = 1/float(premax_ratio)
  3019. if self.preloadimg_prev_zoomratio > 1:
  3020. self.preloadimg_prev_zoomratio = 1
  3021. else:
  3022. if self.currimg_name != "":
  3023. self.image_zoomed = True
  3024. # Calculate zoomratio needed to fit to window:
  3025. win_width = self.available_image_width()
  3026. win_height = self.available_image_height()
  3027. img_width = self.currimg_pixbuf_original.get_width()
  3028. img_height = self.currimg_pixbuf_original.get_height()
  3029. width_ratio = float(img_width)/win_width
  3030. height_ratio = float(img_height)/win_height
  3031. if width_ratio < height_ratio:
  3032. max_ratio = height_ratio
  3033. else:
  3034. max_ratio = width_ratio
  3035. self.currimg_zoomratio = 1/float(max_ratio)
  3036. self.set_zoom_sensitivities()
  3037. if self.currimg_zoomratio > 1:
  3038. # Revert to 1:1 zoom
  3039. self.zoom_1_to_1(action, False, False)
  3040. else:
  3041. self.put_zoom_image_to_window(False)
  3042. self.update_statusbar()
  3043. self.last_image_action_was_fit = True
  3044. self.last_image_action_was_smart_fit = True
  3045. def zoom_1_to_1_action(self, action):
  3046. self.zoom_1_to_1(action, False, False)
  3047. def zoom_1_to_1(self, action, is_preloadimg_next, is_preloadimg_prev):
  3048. if is_preloadimg_next:
  3049. if self.preloading_images:
  3050. self.preloadimg_next_zoomratio = 1
  3051. elif is_preloadimg_prev:
  3052. if self.preloading_images:
  3053. self.preloadimg_prev_zoomratio = 1
  3054. else:
  3055. if self.currimg_name != "" and (self.slideshow_mode or self.currimg_is_animation or (not self.currimg_is_animation and self.UIManager.get_widget('/MainMenu/ViewMenu/1:1').get_property('sensitive'))):
  3056. self.image_zoomed = True
  3057. self.last_mode = self.open_mode_1to1
  3058. self.last_image_action_was_fit = False
  3059. self.currimg_zoomratio = 1
  3060. self.put_zoom_image_to_window(False)
  3061. self.update_statusbar()
  3062. def rotate_left(self, action):
  3063. self.rotate_left_or_right(self.UIManager.get_widget('/MainMenu/EditMenu/Rotate Left'), 90)
  3064. def rotate_right(self, action):
  3065. self.rotate_left_or_right(self.UIManager.get_widget('/MainMenu/EditMenu/Rotate Right'), 270)
  3066. def rotate_left_or_right(self, widget, angle):
  3067. if self.currimg_name != "" and widget.get_property('sensitive'):
  3068. self.currimg_pixbuf_original = self.image_rotate(self.currimg_pixbuf_original, angle)
  3069. if self.last_image_action_was_fit:
  3070. if self.last_image_action_was_smart_fit:
  3071. self.zoom_to_fit_or_1_to_1(None, False, False)
  3072. else:
  3073. self.zoom_to_fit_window(None, False, False)
  3074. else:
  3075. self.currimg_width, self.currimg_height = self.currimg_height, self.currimg_width
  3076. self.layout.set_size(self.currimg_width, self.currimg_height)
  3077. self.currimg_pixbuf = self.image_rotate(self.currimg_pixbuf, angle)
  3078. self.imageview.set_from_pixbuf(self.currimg_pixbuf)
  3079. self.show_scrollbars_if_needed()
  3080. self.center_image()
  3081. self.update_statusbar()
  3082. self.image_modified = True
  3083. def flip_image_vert(self, action):
  3084. self.flip_image_vert_or_horiz(self.UIManager.get_widget('/MainMenu/EditMenu/Flip Vertically'), True)
  3085. def flip_image_horiz(self, action):
  3086. self.flip_image_vert_or_horiz(self.UIManager.get_widget('/MainMenu/EditMenu/Flip Horizontally'), False)
  3087. def flip_image_vert_or_horiz(self, widget, vertical):
  3088. if self.currimg_name != "" and widget.get_property('sensitive'):
  3089. self.currimg_pixbuf = self.image_flip(self.currimg_pixbuf, vertical)
  3090. self.currimg_pixbuf_original = self.image_flip(self.currimg_pixbuf_original, vertical)
  3091. self.imageview.set_from_pixbuf(self.currimg_pixbuf)
  3092. self.image_modified = True
  3093. def get_pixbuf_of_size(self, pixbuf, size, zoom_quality):
  3094. # Creates a pixbuf that fits in the specified square of sizexsize
  3095. # while preserving the aspect ratio
  3096. # Returns tuple: (scaled_pixbuf, actual_width, actual_height)
  3097. image_width = pixbuf.get_width()
  3098. image_height = pixbuf.get_height()
  3099. if image_width-size > image_height-size:
  3100. if image_width > size:
  3101. image_height = int(size/float(image_width)*image_height)
  3102. image_width = size
  3103. else:
  3104. if image_height > size:
  3105. image_width = int(size/float(image_height)*image_width)
  3106. image_height = size
  3107. if not pixbuf.get_has_alpha():
  3108. crop_pixbuf = pixbuf.scale_simple(image_width, image_height, zoom_quality)
  3109. else:
  3110. colormap = self.imageview.get_colormap()
  3111. light_grey = colormap.alloc_color('#666666', True, True)
  3112. dark_grey = colormap.alloc_color('#999999', True, True)
  3113. crop_pixbuf = pixbuf.composite_color_simple(image_width, image_height, zoom_quality, 255, 8, light_grey.pixel, dark_grey.pixel)
  3114. return (crop_pixbuf, image_width, image_height)
  3115. def pixbuf_add_border(self, pix):
  3116. # Add a gray outline to pix. This will increase the pixbuf size by
  3117. # 2 pixels lengthwise and heightwise, 1 on each side. Returns pixbuf.
  3118. try:
  3119. width = pix.get_width()
  3120. height = pix.get_height()
  3121. newpix = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, width+2, height+2)
  3122. newpix.fill(0x858585ff)
  3123. pix.copy_area(0, 0, width, height, newpix, 1, 1)
  3124. return newpix
  3125. except:
  3126. return pix
  3127. def crop_image(self, action):
  3128. dialog = gtk.Dialog(_("Crop Image"), self.window, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
  3129. cropbutton = dialog.add_button(_("C_rop"), gtk.RESPONSE_ACCEPT)
  3130. cropimage = gtk.Image()
  3131. cropimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
  3132. cropbutton.set_image(cropimage)
  3133. image = gtk.DrawingArea()
  3134. crop_pixbuf, image_width, image_height = self.get_pixbuf_of_size(self.currimg_pixbuf_original, 400, self.zoom_quality)
  3135. image.set_size_request(image_width, image_height)
  3136. hbox = gtk.HBox()
  3137. hbox.pack_start(gtk.Label(), expand=True)
  3138. hbox.pack_start(image, expand=False)
  3139. hbox.pack_start(gtk.Label(), expand=True)
  3140. vbox_left = gtk.VBox()
  3141. x_adj = gtk.Adjustment(0, 0, self.currimg_pixbuf_original.get_width(), 1, 10, 0)
  3142. x = gtk.SpinButton(x_adj, 0, 0)
  3143. x.set_numeric(True)
  3144. x.set_update_policy(gtk.UPDATE_IF_VALID)
  3145. x.set_wrap(False)
  3146. x_label = gtk.Label("X:")
  3147. x_label.set_alignment(0, 0.7)
  3148. y_adj = gtk.Adjustment(0, 0, self.currimg_pixbuf_original.get_height(), 1, 10, 0)
  3149. y = gtk.SpinButton(y_adj, 0, 0)
  3150. y.set_numeric(True)
  3151. y.set_update_policy(gtk.UPDATE_IF_VALID)
  3152. y.set_wrap(False)
  3153. y_label = gtk.Label("Y:")
  3154. x_label.set_size_request(y_label.size_request()[0], -1)
  3155. hbox_x = gtk.HBox()
  3156. hbox_y = gtk.HBox()
  3157. hbox_x.pack_start(x_label, False, False, 10)
  3158. hbox_x.pack_start(x, False, False, 0)
  3159. hbox_x.pack_start(gtk.Label(), False, False, 3)
  3160. hbox_y.pack_start(y_label, False, False, 10)
  3161. hbox_y.pack_start(y, False, False, 0)
  3162. hbox_y.pack_start(gtk.Label(), False, False, 3)
  3163. vbox_left.pack_start(hbox_x, False, False, 0)
  3164. vbox_left.pack_start(hbox_y, False, False, 0)
  3165. vbox_right = gtk.VBox()
  3166. width_adj = gtk.Adjustment(self.currimg_pixbuf_original.get_width(), 1, self.currimg_pixbuf_original.get_width(), 1, 10, 0)
  3167. width = gtk.SpinButton(width_adj, 0, 0)
  3168. width.set_numeric(True)
  3169. width.set_update_policy(gtk.UPDATE_IF_VALID)
  3170. width.set_wrap(False)
  3171. width_label = gtk.Label(_("Width:"))
  3172. width_label.set_alignment(0, 0.7)
  3173. height_adj = gtk.Adjustment(self.currimg_pixbuf_original.get_height(), 1, self.currimg_pixbuf_original.get_height(), 1, 10, 0)
  3174. height = gtk.SpinButton(height_adj, 0, 0)
  3175. height.set_numeric(True)
  3176. height.set_update_policy(gtk.UPDATE_IF_VALID)
  3177. height.set_wrap(False)
  3178. height_label = gtk.Label(_("Height:"))
  3179. width_label.set_size_request(height_label.size_request()[0], -1)
  3180. height_label.set_alignment(0, 0.7)
  3181. hbox_width = gtk.HBox()
  3182. hbox_height = gtk.HBox()
  3183. hbox_width.pack_start(width_label, False, False, 10)
  3184. hbox_width.pack_start(width, False, False, 0)
  3185. hbox_height.pack_start(height_label, False, False, 10)
  3186. hbox_height.pack_start(height, False, False, 0)
  3187. vbox_right.pack_start(hbox_width, False, False, 0)
  3188. vbox_right.pack_start(hbox_height, False, False, 0)
  3189. hbox2 = gtk.HBox()
  3190. hbox2.pack_start(gtk.Label(), expand=True)
  3191. hbox2.pack_start(vbox_left, False, False, 0)
  3192. hbox2.pack_start(vbox_right, False, False, 0)
  3193. hbox2.pack_start(gtk.Label(), expand=True)
  3194. dialog.vbox.pack_start(hbox, False, False, 0)
  3195. dialog.vbox.pack_start(hbox2, False, False, 15)
  3196. dialog.set_resizable(False)
  3197. dialog.vbox.show_all()
  3198. image.set_events(gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_MOTION_MASK | gtk.gdk.BUTTON_RELEASE_MASK)
  3199. image.connect("expose-event", self.crop_image_expose_cb, crop_pixbuf, image_width, image_height)
  3200. image.connect("motion_notify_event", self.crop_image_mouse_moved, image, 0, 0, x, y, width, height, image_width, image_height, width_adj, height_adj)
  3201. image.connect("button_press_event", self.crop_image_button_press, image)
  3202. image.connect("button_release_event", self.crop_image_button_release)
  3203. self.x_changed = x.connect('value-changed', self.crop_value_changed, x, y, width, height, width_adj, height_adj, image_width, image_height, image, 0)
  3204. self.y_changed = y.connect('value-changed', self.crop_value_changed, x, y, width, height, width_adj, height_adj, image_width, image_height, image, 1)
  3205. self.width_changed = width.connect('value-changed', self.crop_value_changed, x, y, width, height, width_adj, height_adj, image_width, image_height, image, 2)
  3206. self.height_changed = height.connect('value-changed', self.crop_value_changed, x, y, width, height, width_adj, height_adj, image_width, image_height, image, 3)
  3207. image.realize()
  3208. self.crop_rectangle = [0, 0]
  3209. self.drawing_crop_rectangle = False
  3210. self.update_rectangle = False
  3211. self.rect = None
  3212. response = dialog.run()
  3213. if response == gtk.RESPONSE_ACCEPT:
  3214. dialog.destroy()
  3215. if self.rect != None:
  3216. temp_pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, self.currimg_pixbuf_original.get_has_alpha(), 8, self.coords[2], self.coords[3])
  3217. self.currimg_pixbuf_original.copy_area(self.coords[0], self.coords[1], self.coords[2], self.coords[3], temp_pixbuf, 0, 0)
  3218. self.currimg_pixbuf_original = temp_pixbuf
  3219. del temp_pixbuf
  3220. gc.collect()
  3221. self.load_new_image2(False, True, False, False)
  3222. self.image_modified = True
  3223. else:
  3224. dialog.destroy()
  3225. def crop_value_changed(self, currspinbox, x, y, width, height, width_adj, height_adj, image_width, image_height, image, type):
  3226. if type == 0: # X
  3227. if x.get_value() + width.get_value() > self.currimg_pixbuf_original.get_width():
  3228. width.handler_block(self.width_changed)
  3229. width.set_value(self.currimg_pixbuf_original.get_width() - x.get_value())
  3230. width.handler_unblock(self.width_changed)
  3231. elif type == 1: # Y
  3232. if y.get_value() + height.get_value() > self.currimg_pixbuf_original.get_height():
  3233. height.handler_block(self.height_changed)
  3234. height.set_value(self.currimg_pixbuf_original.get_height() - y.get_value())
  3235. height.handler_unblock(self.height_changed)
  3236. self.coords = [int(x.get_value()), int(y.get_value()), int(width.get_value()), int(height.get_value())]
  3237. self.crop_rectangle[0] = int(round(float(self.coords[0])/self.currimg_pixbuf_original.get_width()*image_width, 0))
  3238. self.crop_rectangle[1] = int(round(float(self.coords[1])/self.currimg_pixbuf_original.get_height()*image_height, 0))
  3239. x2 = int(round(float(self.coords[2])/self.currimg_pixbuf_original.get_width()*image_width, 0)) + self.crop_rectangle[0]
  3240. y2 = int(round(float(self.coords[3])/self.currimg_pixbuf_original.get_height()*image_height, 0)) + self.crop_rectangle[1]
  3241. self.drawing_crop_rectangle = True
  3242. self.update_rectangle = True
  3243. self.crop_image_mouse_moved(None, None, image, x2, y2, x, y, width, height, image_width, image_height, width_adj, height_adj)
  3244. self.update_rectangle = False
  3245. self.drawing_crop_rectangle = False
  3246. def crop_image_expose_cb(self, image, event, pixbuf, width, height):
  3247. image.window.draw_pixbuf(None, pixbuf, 0, 0, 0, 0, width, height)
  3248. def crop_image_mouse_moved(self, widget, event, image, x2, y2, x, y, width, height, image_width, image_height, width_adj, height_adj):
  3249. if event != None:
  3250. x2, y2, state = event.window.get_pointer()
  3251. if self.drawing_crop_rectangle:
  3252. if self.crop_rectangle != None or self.update_rectangle:
  3253. gc = image.window.new_gc(function=gtk.gdk.INVERT)
  3254. if self.rect != None:
  3255. # Get rid of the previous drawn rectangle:
  3256. image.window.draw_rectangle(gc, False, self.rect[0], self.rect[1], self.rect[2], self.rect[3])
  3257. self.rect = [0, 0, 0, 0]
  3258. if self.crop_rectangle[0] > x2:
  3259. self.rect[0] = x2
  3260. self.rect[2] = self.crop_rectangle[0]-x2
  3261. else:
  3262. self.rect[0] = self.crop_rectangle[0]
  3263. self.rect[2] = x2-self.crop_rectangle[0]
  3264. if self.crop_rectangle[1] > y2:
  3265. self.rect[1] = y2
  3266. self.rect[3] = self.crop_rectangle[1]-y2
  3267. else:
  3268. self.rect[1] = self.crop_rectangle[1]
  3269. self.rect[3] = y2-self.crop_rectangle[1]
  3270. image.window.draw_rectangle(gc, False, self.rect[0], self.rect[1], self.rect[2], self.rect[3])
  3271. # Convert the rectangle coordinates of the current image
  3272. # to coordinates of pixbuf_original
  3273. if self.rect[0] < 0:
  3274. self.rect[2] = self.rect[2] + self.rect[0]
  3275. self.rect[0] = 0
  3276. if self.rect[1] < 0:
  3277. self.rect[3] = self.rect[3] + self.rect[1]
  3278. self.rect[1] = 0
  3279. if event != None:
  3280. self.coords = [0,0,0,0]
  3281. self.coords[0] = int(round(float(self.rect[0])/image_width*self.currimg_pixbuf_original.get_width(), 0))
  3282. self.coords[1] = int(round(float(self.rect[1])/image_height*self.currimg_pixbuf_original.get_height(), 0))
  3283. self.coords[2] = int(round(float(self.rect[2])/image_width*self.currimg_pixbuf_original.get_width(), 0))
  3284. self.coords[3] = int(round(float(self.rect[3])/image_height*self.currimg_pixbuf_original.get_height(), 0))
  3285. if self.coords[0] + self.coords[2] > self.currimg_pixbuf_original.get_width():
  3286. self.coords[2] = self.currimg_pixbuf_original.get_width() - self.coords[0]
  3287. if self.coords[1] + self.coords[3] > self.currimg_pixbuf_original.get_height():
  3288. self.coords[3] = self.currimg_pixbuf_original.get_height() - self.coords[1]
  3289. x.handler_block(self.x_changed)
  3290. y.handler_block(self.y_changed)
  3291. width.handler_block(self.width_changed)
  3292. height.handler_block(self.height_changed)
  3293. x.set_value(self.coords[0])
  3294. y.set_value(self.coords[1])
  3295. width.set_value(self.coords[2])
  3296. height.set_value(self.coords[3])
  3297. x.handler_unblock(self.x_changed)
  3298. y.handler_unblock(self.y_changed)
  3299. width_adj.set_property('upper', self.currimg_pixbuf_original.get_width() - self.coords[0])
  3300. height_adj.set_property('upper', self.currimg_pixbuf_original.get_height() - self.coords[1])
  3301. width.handler_unblock(self.width_changed)
  3302. height.handler_unblock(self.height_changed)
  3303. def crop_image_button_press(self, widget, event, image):
  3304. x, y, state = event.window.get_pointer()
  3305. if (state & gtk.gdk.BUTTON1_MASK):
  3306. self.drawing_crop_rectangle = True
  3307. self.crop_rectangle = [x, y]
  3308. gc = image.window.new_gc(function=gtk.gdk.INVERT)
  3309. if self.rect != None:
  3310. # Get rid of the previous drawn rectangle:
  3311. image.window.draw_rectangle(gc, False, self.rect[0], self.rect[1], self.rect[2], self.rect[3])
  3312. self.rect = None
  3313. def crop_image_button_release(self, widget, event):
  3314. x, y, state = event.window.get_pointer()
  3315. if not (state & gtk.gdk.BUTTON1_MASK):
  3316. self.drawing_crop_rectangle = False
  3317. def saturation(self, action):
  3318. dialog = gtk.Dialog(_("Saturation"), self.window, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
  3319. resizebutton = dialog.add_button(_("_Saturate"), gtk.RESPONSE_ACCEPT)
  3320. resizeimage = gtk.Image()
  3321. resizeimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
  3322. resizebutton.set_image(resizeimage)
  3323. scale = gtk.HScale()
  3324. scale.set_draw_value(False)
  3325. scale.set_update_policy(gtk.UPDATE_DISCONTINUOUS)
  3326. scale.set_range(0, 2)
  3327. scale.set_increments(0.1, 0.5)
  3328. scale.set_value(1)
  3329. scale.connect('value-changed', self.saturation_preview)
  3330. label = gtk.Label(_("Saturation level:"))
  3331. label.set_alignment(0, 0.5)
  3332. hbox1 = gtk.HBox()
  3333. hbox1.pack_start(label, True, True, 10)
  3334. hbox2 = gtk.HBox()
  3335. hbox2.pack_start(scale, True, True, 20)
  3336. dialog.vbox.pack_start(gtk.Label(" "))
  3337. dialog.vbox.pack_start(hbox1, False)
  3338. dialog.vbox.pack_start(hbox2, True, True, 10)
  3339. dialog.vbox.pack_start(gtk.Label(" "))
  3340. dialog.set_default_response(gtk.RESPONSE_ACCEPT)
  3341. dialog.vbox.show_all()
  3342. response = dialog.run()
  3343. if response == gtk.RESPONSE_ACCEPT:
  3344. self.currimg_pixbuf_original.saturate_and_pixelate(self.currimg_pixbuf_original, scale.get_value(), False)
  3345. self.currimg_pixbuf.saturate_and_pixelate(self.currimg_pixbuf, scale.get_value(), False)
  3346. self.imageview.set_from_pixbuf(self.currimg_pixbuf)
  3347. self.image_modified = True
  3348. dialog.destroy()
  3349. else:
  3350. self.imageview.set_from_pixbuf(self.currimg_pixbuf)
  3351. dialog.destroy()
  3352. def saturation_preview(self, range):
  3353. while gtk.events_pending():
  3354. gtk.main_iteration()
  3355. try:
  3356. bak = self.currimg_pixbuf.copy()
  3357. self.currimg_pixbuf.saturate_and_pixelate(self.currimg_pixbuf, range.get_value(), False)
  3358. self.imageview.set_from_pixbuf(self.currimg_pixbuf)
  3359. self.currimg_pixbuf = bak.copy()
  3360. del bak
  3361. except:
  3362. pass
  3363. gc.collect()
  3364. def resize_image(self, action):
  3365. dialog = gtk.Dialog(_("Resize Image"), self.window, gtk.DIALOG_MODAL, (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT))
  3366. resizebutton = dialog.add_button(_("_Resize"), gtk.RESPONSE_ACCEPT)
  3367. resizeimage = gtk.Image()
  3368. resizeimage.set_from_stock(gtk.STOCK_OK, gtk.ICON_SIZE_BUTTON)
  3369. resizebutton.set_image(resizeimage)
  3370. hbox_width = gtk.HBox()
  3371. width_adj = gtk.Adjustment(self.currimg_pixbuf_original.get_width(), 1, 100000000000, 1, 10, 0)
  3372. width = gtk.SpinButton(width_adj, 0, 0)
  3373. width.set_numeric(True)
  3374. width.set_update_policy(gtk.UPDATE_IF_VALID)
  3375. width.set_wrap(False)
  3376. width_label = gtk.Label(_("Width:"))
  3377. width_label.set_alignment(0, 0.7)
  3378. hbox_width.pack_start(width_label, False, False, 10)
  3379. hbox_width.pack_start(width, False, False, 0)
  3380. hbox_width.pack_start(gtk.Label(_("pixels")), False, False, 10)
  3381. hbox_height = gtk.HBox()
  3382. height_adj = gtk.Adjustment(self.currimg_pixbuf_original.get_height(), 1, 100000000000, 1, 10, 0)
  3383. height = gtk.SpinButton(height_adj, 0, 0)
  3384. height.set_numeric(True)
  3385. height.set_update_policy(gtk.UPDATE_IF_VALID)
  3386. height.set_wrap(False)
  3387. height_label = gtk.Label(_("Height:"))
  3388. width_label.set_size_request(height_label.size_request()[0], -1)
  3389. height_label.set_alignment(0, 0.7)
  3390. hbox_height.pack_start(height_label, False, False, 10)
  3391. hbox_height.pack_start(height, False, False, 0)
  3392. hbox_height.pack_start(gtk.Label(_("pixels")), False, False, 10)
  3393. hbox_aspect = gtk.HBox()
  3394. aspect_checkbox = gtk.CheckButton(_("Preserve aspect ratio"))
  3395. aspect_checkbox.set_active(self.preserve_aspect)
  3396. hbox_aspect.pack_start(aspect_checkbox, False, False, 10)
  3397. vbox = gtk.VBox()
  3398. vbox.pack_start(gtk.Label(), False, False, 0)
  3399. vbox.pack_start(hbox_width, False, False, 0)
  3400. vbox.pack_start(hbox_height, False, False, 0)
  3401. vbox.pack_start(gtk.Label(), False, False, 0)
  3402. vbox.pack_start(hbox_aspect, False, False, 0)
  3403. vbox.pack_start(gtk.Label(), False, False, 0)
  3404. hbox_total = gtk.HBox()
  3405. animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
  3406. if animtest.is_static_image():
  3407. pixbuf, image_width, image_height = self.get_pixbuf_of_size(self.currimg_pixbuf_original, 96, self.zoom_quality)
  3408. else:
  3409. pixbuf, image_width, image_height = self.get_pixbuf_of_size(animtest.get_static_image(), 96, self.zoom_quality)
  3410. image = gtk.Image()
  3411. image.set_from_pixbuf(self.pixbuf_add_border(pixbuf))
  3412. hbox_total.pack_start(image, False, False, 10)
  3413. hbox_total.pack_start(vbox, False, False, 10)
  3414. dialog.vbox.pack_start(hbox_total, False, False, 0)
  3415. width.connect('value-changed', self.preserve_image_aspect, "width", height)
  3416. height.connect('value-changed', self.preserve_image_aspect, "height", width)
  3417. aspect_checkbox.connect('toggled', self.aspect_ratio_toggled, width, height)
  3418. dialog.set_default_response(gtk.RESPONSE_ACCEPT)
  3419. dialog.vbox.show_all()
  3420. response = dialog.run()
  3421. if response == gtk.RESPONSE_ACCEPT:
  3422. pixelheight = height.get_value_as_int()
  3423. pixelwidth = width.get_value_as_int()
  3424. dialog.destroy()
  3425. self.currimg_pixbuf_original = self.currimg_pixbuf_original.scale_simple(pixelwidth, pixelheight, self.zoom_quality)
  3426. self.load_new_image2(False, True, False, False)
  3427. self.image_modified = True
  3428. else:
  3429. dialog.destroy()
  3430. def aspect_ratio_toggled(self, togglebutton, width, height):
  3431. self.preserve_aspect = togglebutton.get_active()
  3432. if self.preserve_aspect:
  3433. # Set height based on width and aspect ratio
  3434. target_value = float(width.get_value_as_int())/self.currimg_pixbuf_original.get_width()
  3435. target_value = int(target_value * self.currimg_pixbuf_original.get_height())
  3436. self.ignore_preserve_aspect_callback = True
  3437. height.set_value(target_value)
  3438. self.ignore_preserve_aspect_callback = False
  3439. def preserve_image_aspect(self, currspinbox, type, otherspinbox):
  3440. if not self.preserve_aspect:
  3441. return
  3442. if self.ignore_preserve_aspect_callback:
  3443. return
  3444. if type == "width":
  3445. target_value = float(currspinbox.get_value_as_int())/self.currimg_pixbuf_original.get_width()
  3446. target_value = int(target_value * self.currimg_pixbuf_original.get_height())
  3447. else:
  3448. target_value = float(currspinbox.get_value_as_int())/self.currimg_pixbuf_original.get_height()
  3449. target_value = int(target_value * self.currimg_pixbuf_original.get_width())
  3450. self.ignore_preserve_aspect_callback = True
  3451. otherspinbox.set_value(target_value)
  3452. self.ignore_preserve_aspect_callback = False
  3453. def goto_prev_image(self, action):
  3454. self.goto_image("PREV", action)
  3455. def goto_next_image(self, action):
  3456. self.goto_image("NEXT", action)
  3457. def goto_random_image(self, action):
  3458. self.goto_image("RANDOM", action)
  3459. def goto_first_image(self, action):
  3460. self.goto_image("FIRST", action)
  3461. def goto_last_image(self, action):
  3462. self.goto_image("LAST", action)
  3463. def goto_image(self, location, action):
  3464. # location can be "LAST", "FIRST", "NEXT", "PREV", "RANDOM", or a number
  3465. if self.slideshow_mode and action != "ss":
  3466. gobject.source_remove(self.timer_delay)
  3467. if ((location=="PREV" or location=="NEXT" or location=="RANDOM") and len(self.image_list) > 1) or (location=="FIRST" and (len(self.image_list) > 1 and self.curr_img_in_list != 0)) or (location=="LAST" and (len(self.image_list) > 1 and self.curr_img_in_list != len(self.image_list)-1)) or valid_int(location):
  3468. self.load_new_image_stop_now()
  3469. cancel = self.autosave_image()
  3470. if cancel:
  3471. return
  3472. check_wrap = False
  3473. if location != "RANDOM":
  3474. self.randomlist = []
  3475. if location == "FIRST":
  3476. self.curr_img_in_list = 0
  3477. elif location == "RANDOM":
  3478. if self.randomlist == []:
  3479. self.reinitialize_randomlist()
  3480. else:
  3481. # check if we have seen every image; if so, reinitialize array and repeat:
  3482. all_items_are_true = True
  3483. for item in self.randomlist:
  3484. if not item:
  3485. all_items_are_true = False
  3486. if all_items_are_true:
  3487. if not self.slideshow_mode or (self.slideshow_mode and self.listwrap_mode == 1):
  3488. self.reinitialize_randomlist()
  3489. else:
  3490. check_wrap = True
  3491. elif location == "LAST":
  3492. self.curr_img_in_list = len(self.image_list)-1
  3493. elif location == "PREV":
  3494. if self.curr_img_in_list > 0:
  3495. self.curr_img_in_list -= 1
  3496. else:
  3497. check_wrap = True
  3498. elif location == "NEXT":
  3499. if self.curr_img_in_list < len(self.image_list) - 1:
  3500. self.curr_img_in_list += 1
  3501. else:
  3502. check_wrap = True
  3503. if check_wrap:
  3504. if self.listwrap_mode == 0:
  3505. if location == "NEXT":
  3506. if self.slideshow_mode:
  3507. self.toggle_slideshow(None)
  3508. return
  3509. elif (location == "PREV" or location == "NEXT") and self.listwrap_mode == 1:
  3510. if location == "PREV":
  3511. self.curr_img_in_list = len(self.image_list) - 1
  3512. elif location == "NEXT":
  3513. self.curr_img_in_list = 0
  3514. else:
  3515. if self.curr_img_in_list != self.loaded_img_in_list:
  3516. # Ensure that the user is looking at the correct "last" image before
  3517. # they are asked the wrap question:
  3518. if location == "PREV":
  3519. self.load_new_image(True, False, True, True, True, True)
  3520. else:
  3521. self.load_new_image(False, False, True, True, True, True)
  3522. self.set_go_navigation_sensitivities(False)
  3523. self.thumbpane_select(self.curr_img_in_list)
  3524. if self.fullscreen_mode:
  3525. self.change_cursor(None)
  3526. if location == "PREV":
  3527. dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _("You are viewing the first image in the list. Wrap around to the last image?"))
  3528. elif location == "NEXT":
  3529. dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _("You are viewing the last image in the list. Wrap around to the first image?"))
  3530. elif location == "RANDOM":
  3531. dialog = gtk.MessageDialog(self.window, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, _("All images have been viewed. Would you like to cycle through the images again?"))
  3532. dialog.set_title(_("Wrap?"))
  3533. dialog.label.set_property('can-focus', False)
  3534. dialog.set_default_response(gtk.RESPONSE_YES)
  3535. self.user_prompt_visible = True
  3536. response = dialog.run()
  3537. if response == gtk.RESPONSE_YES:
  3538. if location == "PREV":
  3539. self.curr_img_in_list = len(self.image_list)-1
  3540. elif location == "NEXT":
  3541. self.curr_img_in_list = 0
  3542. elif location == "RANDOM":
  3543. self.reinitialize_randomlist()
  3544. dialog.destroy()
  3545. self.user_prompt_visible = False
  3546. if self.fullscreen_mode:
  3547. self.hide_cursor
  3548. else:
  3549. dialog.destroy()
  3550. self.user_prompt_visible = False
  3551. if self.fullscreen_mode:
  3552. self.hide_cursor
  3553. else:
  3554. self.change_cursor(None)
  3555. if self.slideshow_mode:
  3556. self.toggle_slideshow(None)
  3557. return
  3558. if location == "RANDOM":
  3559. # Find random image that hasn't already been chosen:
  3560. j = random.randint(0, len(self.image_list)-1)
  3561. while self.randomlist[j]:
  3562. j = random.randint(0, len(self.image_list)-1)
  3563. self.curr_img_in_list = j
  3564. self.randomlist[j] = True
  3565. self.currimg_name = str(self.image_list[self.curr_img_in_list])
  3566. if valid_int(location):
  3567. prev_img = self.curr_img_in_list
  3568. self.curr_img_in_list = int(location)
  3569. if not self.fullscreen_mode and (not self.slideshow_mode or (self.slideshow_mode and action != "ss")):
  3570. self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
  3571. if location == "PREV" or (valid_int(location) and int(location) == prev_img-1):
  3572. self.load_when_idle = gobject.idle_add(self.load_new_image, True, False, True, True, True, True)
  3573. else:
  3574. self.load_when_idle = gobject.idle_add(self.load_new_image, False, False, True, True, True, True)
  3575. self.set_go_navigation_sensitivities(False)
  3576. if self.slideshow_mode:
  3577. if self.curr_slideshow_random:
  3578. self.timer_delay = gobject.timeout_add(int(self.curr_slideshow_delay*1000), self.goto_random_image, "ss")
  3579. else:
  3580. self.timer_delay = gobject.timeout_add(int(self.curr_slideshow_delay*1000), self.goto_next_image, "ss")
  3581. gobject.idle_add(self.thumbpane_select, self.curr_img_in_list)
  3582. def set_go_navigation_sensitivities(self, skip_initial_check):
  3583. # setting skip_image_list_check to True is useful when calling from
  3584. # expand_filelist_and_load_image() for example, as self.image_list has not
  3585. # yet fully populated
  3586. if (not self.image_loaded or len(self.image_list) == 1) and not skip_initial_check:
  3587. self.set_previous_image_sensitivities(False)
  3588. self.set_first_image_sensitivities(False)
  3589. self.set_next_image_sensitivities(False)
  3590. self.set_last_image_sensitivities(False)
  3591. self.set_random_image_sensitivities(False)
  3592. elif self.curr_img_in_list == 0:
  3593. if self.listwrap_mode == 0:
  3594. self.set_previous_image_sensitivities(False)
  3595. else:
  3596. self.set_previous_image_sensitivities(True)
  3597. self.set_first_image_sensitivities(False)
  3598. self.set_next_image_sensitivities(True)
  3599. self.set_last_image_sensitivities(True)
  3600. self.set_random_image_sensitivities(True)
  3601. elif self.curr_img_in_list == len(self.image_list)-1:
  3602. self.set_previous_image_sensitivities(True)
  3603. self.set_first_image_sensitivities(True)
  3604. if self.listwrap_mode == 0:
  3605. self.set_next_image_sensitivities(False)
  3606. else:
  3607. self.set_next_image_sensitivities(True)
  3608. self.set_last_image_sensitivities(False)
  3609. self.set_random_image_sensitivities(True)
  3610. else:
  3611. self.set_previous_image_sensitivities(True)
  3612. self.set_first_image_sensitivities(True)
  3613. self.set_next_image_sensitivities(True)
  3614. self.set_last_image_sensitivities(True)
  3615. self.set_random_image_sensitivities(True)
  3616. def reinitialize_randomlist(self):
  3617. self.randomlist = []
  3618. for i in range(len(self.image_list)):
  3619. self.randomlist.append(False)
  3620. self.randomlist[self.curr_img_in_list] = True
  3621. def image_load_failed(self, reset_cursor, filename=""):
  3622. # If a filename is provided, use it for display:
  3623. if len(filename) == 0:
  3624. self.currimg_name = str(self.image_list[self.curr_img_in_list])
  3625. else:
  3626. self.currmg_name = filename
  3627. if self.verbose and self.currimg_name != "":
  3628. print _("Yükleniyor: %s") % self.currimg_name
  3629. self.update_title()
  3630. self.put_error_image_to_window()
  3631. self.image_loaded = False
  3632. self.currimg_pixbuf_original = None
  3633. if reset_cursor:
  3634. if not self.fullscreen_mode:
  3635. self.change_cursor(None)
  3636. def load_new_image_stop_now(self):
  3637. try:
  3638. gobject.source_remove(self.load_when_idle)
  3639. except:
  3640. pass
  3641. try:
  3642. gobject.source_remove(self.preload_when_idle)
  3643. except:
  3644. pass
  3645. try:
  3646. gobject.source_remove(self.preload_when_idle2)
  3647. except:
  3648. pass
  3649. def load_new_image(self, check_prev_last, use_current_pixbuf_original, reset_cursor, perform_onload_action, preload_next_image_after, preload_prev_image_after):
  3650. try:
  3651. self.load_new_image2(check_prev_last, use_current_pixbuf_original, reset_cursor, perform_onload_action)
  3652. except:
  3653. self.image_load_failed(True)
  3654. if preload_next_image_after:
  3655. self.preload_when_idle = gobject.idle_add(self.preload_next_image, False)
  3656. if preload_prev_image_after:
  3657. self.preload_when_idle2 = gobject.idle_add(self.preload_prev_image, False)
  3658. def check_preloadimg_prev_for_existing(self, prev_index, reset_preloadimg_prev_in_list):
  3659. # Determines if preloadimg_prev needs to be updated; if so,
  3660. # checks if the image is already stored in self.currimg
  3661. # or self.preloadimg_next and can be reused.
  3662. reset_preloadimg_prev_in_list = False
  3663. if prev_index != self.preloadimg_prev_in_list and prev_index != -1:
  3664. # Need to update preloadimg_prev:
  3665. if prev_index == self.loaded_img_in_list and not self.image_modified and not self.image_zoomed:
  3666. self.preloadimg_prev_in_list = self.loaded_img_in_list
  3667. self.preloadimg_prev_name = self.currimg_name
  3668. self.preloadimg_prev_width = self.currimg_width
  3669. self.preloadimg_prev_height = self.currimg_height
  3670. self.preloadimg_prev_pixbuf = self.currimg_pixbuf
  3671. self.preloadimg_prev_pixbuf_original = self.currimg_pixbuf_original
  3672. self.preloadimg_prev_zoomratio = self.currimg_zoomratio
  3673. self.preloadimg_prev_is_animation = self.currimg_is_animation
  3674. elif prev_index == self.preloadimg_next_in_list:
  3675. self.preloadimg_prev_in_list = self.preloadimg_next_in_list
  3676. self.preloadimg_prev_name = self.preloadimg_next_name
  3677. self.preloadimg_prev_width = self.preloadimg_next_width
  3678. self.preloadimg_prev_height = self.preloadimg_next_height
  3679. self.preloadimg_prev_pixbuf = self.preloadimg_next_pixbuf
  3680. self.preloadimg_prev_pixbuf_original = self.preloadimg_next_pixbuf_original
  3681. self.preloadimg_prev_zoomratio = self.preloadimg_next_zoomratio
  3682. self.preloadimg_prev_is_animation = self.preloadimg_next_is_animation
  3683. else:
  3684. reset_preloadimg_prev_in_list = True
  3685. elif prev_index == -1:
  3686. reset_preloadimg_prev_in_list = True
  3687. def check_preloadimg_next_for_existing(self, next_index, reset_preloadimg_next_in_list):
  3688. # Determines if preloadimg_next needs to be updated; if so,
  3689. # checks if the image is already stored in self.currimg
  3690. # or self.preloadimg_prev and can be reused.
  3691. reset_preloadimg_next_in_list = False
  3692. if next_index != self.preloadimg_next_in_list and next_index != -1:
  3693. # Need to update preloadimg_next:
  3694. if next_index == self.loaded_img_in_list and not self.image_modified and not self.image_zoomed:
  3695. self.preloadimg_next_in_list = self.loaded_img_in_list
  3696. self.preloadimg_next_name = self.currimg_name
  3697. self.preloadimg_next_width = self.currimg_width
  3698. self.preloadimg_next_height = self.currimg_height
  3699. self.preloadimg_next_pixbuf = self.currimg_pixbuf
  3700. self.preloadimg_next_pixbuf_original = self.currimg_pixbuf_original
  3701. self.preloadimg_next_zoomratio = self.currimg_zoomratio
  3702. self.preloadimg_next_is_animation = self.currimg_is_animation
  3703. elif next_index == self.preloadimg_prev_in_list:
  3704. self.preloadimg_next_in_list = self.preloadimg_prev_in_list
  3705. self.preloadimg_next_name = self.preloadimg_prev_name
  3706. self.preloadimg_next_width = self.preloadimg_prev_width
  3707. self.preloadimg_next_height = self.preloadimg_prev_height
  3708. self.preloadimg_next_pixbuf = self.preloadimg_prev_pixbuf
  3709. self.preloadimg_next_pixbuf_original = self.preloadimg_prev_pixbuf_original
  3710. self.preloadimg_next_zoomratio = self.preloadimg_prev_zoomratio
  3711. self.preloadimg_next_is_animation = self.preloadimg_prev_is_animation
  3712. else:
  3713. reset_preloadimg_next_in_list = True
  3714. elif next_index == -1:
  3715. reset_preloadimg_next_in_list = True
  3716. def check_currimg_for_existing(self):
  3717. # Determines if currimg needs to be updated; if so,
  3718. # checks if the image is already stored in self.preloadimg_next
  3719. # or self.preloadimg_prev and can be reused (the whole point of
  3720. # preloading!)
  3721. used_prev = False
  3722. used_next = False
  3723. if self.curr_img_in_list != self.loaded_img_in_list:
  3724. # Need to update currimg:
  3725. if self.curr_img_in_list == self.preloadimg_prev_in_list:
  3726. # Set preload_prev_image as current image
  3727. self.currimg_name = self.preloadimg_prev_name
  3728. self.currimg_width = self.preloadimg_prev_width
  3729. self.currimg_height = self.preloadimg_prev_height
  3730. self.currimg_pixbuf = self.preloadimg_prev_pixbuf
  3731. self.currimg_pixbuf_original = self.preloadimg_prev_pixbuf_original
  3732. self.currimg_zoomratio = self.preloadimg_prev_zoomratio
  3733. self.currimg_is_animation = self.preloadimg_prev_is_animation
  3734. used_prev = True
  3735. if self.verbose and self.currimg_name != "":
  3736. print _("Loading: %s") % self.currimg_name
  3737. self.put_zoom_image_to_window(True)
  3738. if not self.currimg_is_animation:
  3739. self.set_image_sensitivities(True)
  3740. else:
  3741. self.set_image_sensitivities(False)
  3742. elif self.curr_img_in_list == self.preloadimg_next_in_list:
  3743. # Use preload_next_image as current image
  3744. self.currimg_name = self.preloadimg_next_name
  3745. self.currimg_width = self.preloadimg_next_width
  3746. self.currimg_height = self.preloadimg_next_height
  3747. self.currimg_pixbuf = self.preloadimg_next_pixbuf
  3748. self.currimg_pixbuf_original = self.preloadimg_next_pixbuf_original
  3749. self.currimg_zoomratio = self.preloadimg_next_zoomratio
  3750. self.currimg_is_animation = self.preloadimg_next_is_animation
  3751. used_next = True
  3752. if self.verbose and self.currimg_name != "":
  3753. print _("Yükleniyor: %s") % self.currimg_name
  3754. self.put_zoom_image_to_window(True)
  3755. if not self.currimg_is_animation:
  3756. self.set_image_sensitivities(True)
  3757. else:
  3758. self.set_image_sensitivities(False)
  3759. return used_prev, used_next
  3760. def load_new_image2(self, check_prev_last, use_current_pixbuf_original, reset_cursor, perform_onload_action, skip_recentfiles=False):
  3761. # check_prev_last is used to determine if we should check whether
  3762. # preloadimg_prev can be reused last. This should really only
  3763. # be done if the user just clicked the previous image button in
  3764. # order to reduce the number of image loads.
  3765. # If use_current_pixbuf_original == True, do not reload the
  3766. # self.currimg_pixbuf_original from the file; instead, use the existing
  3767. # one. This is only currently useful for resizing images.
  3768. # Determine the indices in the self.image_list array for the
  3769. # previous and next preload images.
  3770. next_index = self.curr_img_in_list + 1
  3771. if next_index > len(self.image_list)-1:
  3772. if self.listwrap_mode == 0:
  3773. next_index = -1
  3774. else:
  3775. next_index = 0
  3776. prev_index = self.curr_img_in_list - 1
  3777. if prev_index < 0:
  3778. if self.listwrap_mode == 0:
  3779. prev_index = -1
  3780. else:
  3781. prev_index = len(self.image_list)-1
  3782. if self.preloading_images:
  3783. reset_preloadimg_next_in_list = False
  3784. reset_preloadimg_prev_in_list = False
  3785. if check_prev_last:
  3786. self.check_preloadimg_next_for_existing(next_index, reset_preloadimg_next_in_list)
  3787. else:
  3788. self.check_preloadimg_prev_for_existing(prev_index, reset_preloadimg_prev_in_list)
  3789. used_prev, used_next = self.check_currimg_for_existing()
  3790. if self.preloading_images:
  3791. if check_prev_last:
  3792. self.check_preloadimg_prev_for_existing(prev_index, reset_preloadimg_prev_in_list)
  3793. else:
  3794. self.check_preloadimg_next_for_existing(next_index, reset_preloadimg_next_in_list)
  3795. if reset_preloadimg_prev_in_list:
  3796. self.preloadimg_prev_in_list = -1
  3797. if reset_preloadimg_next_in_list:
  3798. self.preloadimg_next_in_list = -1
  3799. if used_prev or used_next:
  3800. # If we used a preload image, set the correct boolean variables
  3801. if self.open_mode == self.open_mode_smart or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_smart):
  3802. self.last_image_action_was_fit = True
  3803. self.last_image_action_was_smart_fit = True
  3804. elif self.open_mode == self.open_mode_fit or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_fit):
  3805. self.last_image_action_was_fit = True
  3806. self.last_image_action_was_smart_fit = False
  3807. elif self.open_mode == self.open_mode_1to1 or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_1to1):
  3808. self.last_image_action_was_fit = False
  3809. else:
  3810. # Need to load the current image
  3811. self.currimg_pixbuf = None
  3812. self.currimg_zoomratio = 1
  3813. self.currimg_name = str(self.image_list[self.curr_img_in_list])
  3814. if self.verbose and self.currimg_name != "":
  3815. print _("Yükleniyor: %s") % self.currimg_name
  3816. animtest = gtk.gdk.PixbufAnimation(self.currimg_name)
  3817. if animtest.is_static_image() or (use_current_pixbuf_original and not self.currimg_is_animation):
  3818. self.currimg_is_animation = False
  3819. if not use_current_pixbuf_original:
  3820. self.currimg_pixbuf_original = animtest.get_static_image()
  3821. self.set_image_sensitivities(True)
  3822. if self.open_mode == self.open_mode_smart or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_smart):
  3823. self.zoom_to_fit_or_1_to_1(None, False, False)
  3824. elif self.open_mode == self.open_mode_fit or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_fit):
  3825. self.zoom_to_fit_window(None, False, False)
  3826. elif self.open_mode == self.open_mode_1to1 or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_1to1):
  3827. self.zoom_1_to_1(None, False, False)
  3828. else:
  3829. self.currimg_is_animation = True
  3830. if not use_current_pixbuf_original:
  3831. self.currimg_pixbuf_original = animtest
  3832. self.zoom_1_to_1(None, False, False)
  3833. self.set_image_sensitivities(False)
  3834. if self.onload_cmd != None and perform_onload_action:
  3835. self.parse_action_command(self.onload_cmd, False)
  3836. self.update_statusbar()
  3837. self.update_title()
  3838. self.image_loaded = True
  3839. self.image_modified = False
  3840. self.image_zoomed = False
  3841. self.set_slideshow_sensitivities()
  3842. if not skip_recentfiles:
  3843. self.register_file_with_recent_docs(self.currimg_name)
  3844. if reset_cursor:
  3845. if not self.fullscreen_mode:
  3846. self.change_cursor(None)
  3847. def preload_next_image(self, use_existing_image):
  3848. try:
  3849. if self.preloading_images and len(self.image_list) > 1:
  3850. if not use_existing_image:
  3851. next_index = self.curr_img_in_list + 1
  3852. if next_index > len(self.image_list)-1:
  3853. if self.listwrap_mode == 0:
  3854. self.preloadimg_next_in_list == -1
  3855. return
  3856. else:
  3857. next_index = 0
  3858. if next_index == self.preloadimg_next_in_list:
  3859. return
  3860. self.preloadimg_next_in_list = next_index
  3861. self.preloadimg_next_name = str(self.image_list[next_index])
  3862. pre_animtest = gtk.gdk.PixbufAnimation(self.preloadimg_next_name)
  3863. if pre_animtest.is_static_image():
  3864. self.preloadimg_next_is_animation = False
  3865. self.preloadimg_next_pixbuf_original = pre_animtest.get_static_image()
  3866. else:
  3867. self.preloadimg_next_is_animation = True
  3868. self.preloadimg_next_pixbuf_original = pre_animtest
  3869. if self.preloadimg_next_in_list == -1:
  3870. return
  3871. # Determine self.preloadimg_next_zoomratio
  3872. if self.open_mode == self.open_mode_smart or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_smart):
  3873. self.zoom_to_fit_or_1_to_1(None, True, False)
  3874. elif self.open_mode == self.open_mode_fit or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_fit):
  3875. self.zoom_to_fit_window(None, True, False)
  3876. elif self.open_mode == self.open_mode_1to1 or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_1to1):
  3877. self.zoom_1_to_1(None, True, False)
  3878. # Always start with the original image to preserve quality!
  3879. # Calculate image size:
  3880. self.preloadimg_next_width = int(self.preloadimg_next_pixbuf_original.get_width() * self.preloadimg_next_zoomratio)
  3881. self.preloadimg_next_height = int(self.preloadimg_next_pixbuf_original.get_height() * self.preloadimg_next_zoomratio)
  3882. if not self.preloadimg_next_is_animation:
  3883. # Scale image:
  3884. if not self.preloadimg_next_pixbuf_original.get_has_alpha():
  3885. self.preloadimg_next_pixbuf = self.preloadimg_next_pixbuf_original.scale_simple(self.preloadimg_next_width, self.preloadimg_next_height, self.zoom_quality)
  3886. else:
  3887. colormap = self.imageview.get_colormap()
  3888. light_grey = colormap.alloc_color('#666666', True, True)
  3889. dark_grey = colormap.alloc_color('#999999', True, True)
  3890. self.preloadimg_next_pixbuf = self.preloadimg_next_pixbuf_original.composite_color_simple(self.preloadimg_next_width, self.preloadimg_next_height, self.zoom_quality, 255, 8, light_grey.pixel, dark_grey.pixel)
  3891. else:
  3892. self.preloadimg_next_pixbuf = self.preloadimg_next_pixbuf_original
  3893. gc.collect()
  3894. if self.verbose:
  3895. print _("Preloading: %s") % self.preloadimg_next_name
  3896. except:
  3897. self.preloadimg_next_in_list = -1
  3898. def preload_prev_image(self, use_existing_image):
  3899. try:
  3900. if self.preloading_images and len(self.image_list) > 1:
  3901. if not use_existing_image:
  3902. prev_index = self.curr_img_in_list - 1
  3903. if prev_index < 0:
  3904. if self.listwrap_mode == 0:
  3905. self.preloadimg_prev_in_list == -1
  3906. return
  3907. else:
  3908. prev_index = len(self.image_list)-1
  3909. if prev_index == self.preloadimg_prev_in_list:
  3910. return
  3911. self.preloadimg_prev_in_list = prev_index
  3912. self.preloadimg_prev_name = str(self.image_list[prev_index])
  3913. pre_animtest = gtk.gdk.PixbufAnimation(self.preloadimg_prev_name)
  3914. if pre_animtest.is_static_image():
  3915. self.preloadimg_prev_is_animation = False
  3916. self.preloadimg_prev_pixbuf_original = pre_animtest.get_static_image()
  3917. else:
  3918. self.preloadimg_prev_is_animation = True
  3919. self.preloadimg_prev_pixbuf_original = pre_animtest
  3920. if self.preloadimg_prev_in_list == -1:
  3921. return
  3922. # Determine self.preloadimg_prev_zoomratio
  3923. if self.open_mode == self.open_mode_smart or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_smart):
  3924. self.zoom_to_fit_or_1_to_1(None, False, True)
  3925. elif self.open_mode == self.open_mode_fit or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_fit):
  3926. self.zoom_to_fit_window(None, False, True)
  3927. elif self.open_mode == self.open_mode_1to1 or (self.open_mode == self.open_mode_last and self.last_mode == self.open_mode_1to1):
  3928. self.zoom_1_to_1(None, False, True)
  3929. # Always start with the original image to preserve quality!
  3930. # Calculate image size:
  3931. self.preloadimg_prev_width = int(self.preloadimg_prev_pixbuf_original.get_width() * self.preloadimg_prev_zoomratio)
  3932. self.preloadimg_prev_height = int(self.preloadimg_prev_pixbuf_original.get_height() * self.preloadimg_prev_zoomratio)
  3933. if not self.preloadimg_prev_is_animation:
  3934. # Scale image:
  3935. if not self.preloadimg_prev_pixbuf_original.get_has_alpha():
  3936. self.preloadimg_prev_pixbuf = self.preloadimg_prev_pixbuf_original.scale_simple(self.preloadimg_prev_width, self.preloadimg_prev_height, self.zoom_quality)
  3937. else:
  3938. colormap = self.imageview.get_colormap()
  3939. light_grey = colormap.alloc_color('#666666', True, True)
  3940. dark_grey = colormap.alloc_color('#999999', True, True)
  3941. self.preloadimg_prev_pixbuf = self.preloadimg_prev_pixbuf_original.composite_color_simple(self.preloadimg_prev_width, self.preloadimg_prev_height, self.zoom_quality, 255, 8, light_grey.pixel, dark_grey.pixel)
  3942. else:
  3943. self.preloadimg_prev_pixbuf = self.preloadimg_prev_pixbuf_original
  3944. gc.collect()
  3945. if self.verbose:
  3946. print _("Preloading: %s") % self.preloadimg_prev_name
  3947. except:
  3948. self.preloadimg_prev_in_list = -1
  3949. def change_cursor(self, type):
  3950. for i in gtk.gdk.window_get_toplevels():
  3951. if i.get_window_type() != gtk.gdk.WINDOW_TEMP and i.get_window_type() != gtk.gdk.WINDOW_CHILD:
  3952. i.set_cursor(type)
  3953. self.layout.window.set_cursor(type)
  3954. def expand_filelist_and_load_image(self, inputlist):
  3955. # Takes the current list (i.e. ["pic.jpg", "pic2.gif", "../images"]) and
  3956. # expands it into a list of all pictures found
  3957. self.thumblist.clear()
  3958. first_image_loaded_successfully = False
  3959. self.images_found = 0
  3960. self.stop_now = True # Make sure that any previous search process is stopped
  3961. self.change_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
  3962. # Reset preload images:
  3963. self.preloadimg_next_in_list = -1
  3964. self.preloadimg_prev_in_list = -1
  3965. # If any directories were passed, display "Searching..." in statusbar:
  3966. self.searching_for_images = False
  3967. for item in inputlist:
  3968. if os.path.isdir(item):
  3969. self.searching_for_images = True
  3970. self.update_statusbar()
  3971. if not self.closing_app:
  3972. while gtk.events_pending():
  3973. gtk.main_iteration()
  3974. first_image = ""
  3975. first_image_found = False
  3976. first_image_loaded = False
  3977. second_image = ""
  3978. second_image_found = False
  3979. second_image_preloaded = False
  3980. self.randomlist = []
  3981. folderlist = []
  3982. self.image_list = []
  3983. self.curr_img_in_list = 0
  3984. go_buttons_enabled = False
  3985. self.set_go_sensitivities(False)
  3986. # Clean up list (remove preceding "file://" or "file:" and trailing "/")
  3987. for itemnum in range(len(inputlist)):
  3988. # Strip off preceding file..
  3989. if inputlist[itemnum].startswith('file://'):
  3990. inputlist[itemnum] = inputlist[itemnum][7:]
  3991. elif inputlist[itemnum].startswith('file:'):
  3992. inputlist[itemnum] = inputlist[itemnum][5:]
  3993. # Strip off trailing "/" if it exists:
  3994. if inputlist[itemnum][len(inputlist[itemnum])-1] == "/":
  3995. inputlist[itemnum] = inputlist[itemnum][:(len(inputlist[itemnum])-1)]
  3996. if not (inputlist[itemnum].startswith('http://') or inputlist[itemnum].startswith('ftp://')):
  3997. inputlist[itemnum] = os.path.abspath(inputlist[itemnum])
  3998. else:
  3999. try:
  4000. # Remote file. Save as /tmp/mirage-<random>/filename.ext
  4001. tmpdir = tempfile.mkdtemp(prefix="mirage-") + "/"
  4002. tmpfile = tmpdir + os.path.basename(inputlist[itemnum])
  4003. socket.setdefaulttimeout(5)
  4004. urllib.urlretrieve(inputlist[itemnum], tmpfile)
  4005. inputlist[itemnum] = tmpfile
  4006. except:
  4007. pass
  4008. # Remove hidden files from list:
  4009. if not self.open_hidden_files:
  4010. tmplist = []
  4011. for item in inputlist:
  4012. if os.path.basename(item)[0] != '.':
  4013. tmplist.append(item)
  4014. elif self.verbose:
  4015. print _("Atlanıyor: %s") % item
  4016. inputlist = tmplist
  4017. if len(inputlist) == 0:
  4018. # All files/dirs were hidden, exit..
  4019. self.currimg_name = ""
  4020. self.searching_for_images = False
  4021. self.set_go_navigation_sensitivities(False)
  4022. self.set_slideshow_sensitivities()
  4023. if not self.closing_app:
  4024. self.change_cursor(None)
  4025. self.recursive = False
  4026. self.put_error_image_to_window()
  4027. self.update_title()
  4028. return
  4029. init_image = os.path.abspath(inputlist[0])
  4030. self.stop_now = False
  4031. # If open all images in dir...
  4032. if self.open_all_images:
  4033. temp = inputlist
  4034. inputlist = []
  4035. for item in temp:
  4036. if os.path.isfile(item):
  4037. itempath = os.path.dirname(os.path.abspath(item))
  4038. temp = self.recursive
  4039. self.recursive = False
  4040. self.stop_now = False
  4041. self.expand_directory(itempath, False, go_buttons_enabled, False, False)
  4042. self.recursive = temp
  4043. else:
  4044. inputlist.append(item)
  4045. for item in self.image_list:
  4046. inputlist.append(item)
  4047. if first_image_found and not second_image_found:
  4048. second_image_found = True
  4049. second_image = item
  4050. second_image_came_from_dir = False
  4051. if item == init_image:
  4052. first_image_found = True
  4053. first_image = item
  4054. first_image_came_from_dir = False
  4055. self.curr_img_in_list = len(inputlist)-1
  4056. self.image_list = []
  4057. for item in inputlist:
  4058. if not self.closing_app:
  4059. if os.path.isfile(item):
  4060. if self.valid_image(item):
  4061. if not second_image_found and first_image_found:
  4062. second_image_found = True
  4063. second_image = item
  4064. second_image_came_from_dir = False
  4065. if not first_image_found:
  4066. first_image_found = True
  4067. first_image = item
  4068. first_image_came_from_dir = False
  4069. self.image_list.append(item)
  4070. if self.verbose:
  4071. self.images_found += 1
  4072. print _("Found: %(item)s [%(number)i]") % {'item': item, 'number': self.images_found}
  4073. else:
  4074. # If it's a directory that was explicitly selected or passed to
  4075. # the program, get all the files in the dir.
  4076. # Retrieve only images in the top directory specified by the user
  4077. # unless explicitly told to recurse (via -R or in Settings>Preferences)
  4078. folderlist.append(item)
  4079. if not second_image_found:
  4080. # See if we can find an image in this directory:
  4081. self.stop_now = False
  4082. self.expand_directory(item, True, go_buttons_enabled, False, False)
  4083. itemnum = 0
  4084. while itemnum < len(self.image_list) and not second_image_found:
  4085. if os.path.isfile(self.image_list[itemnum]):
  4086. if not second_image_found and first_image_found:
  4087. second_image_found = True
  4088. second_image_came_from_dir = True
  4089. second_image = self.image_list[itemnum]
  4090. self.set_go_navigation_sensitivities(True)
  4091. go_buttons_enabled = True
  4092. while gtk.events_pending():
  4093. gtk.main_iteration(True)
  4094. if not first_image_found:
  4095. first_image_found = True
  4096. first_image = self.image_list[itemnum]
  4097. first_image_came_from_dir = True
  4098. itemnum += 1
  4099. # Load first image and display:
  4100. if first_image_found and not first_image_loaded and self.curr_img_in_list <= len(self.image_list)-1:
  4101. first_image_loaded = True
  4102. if self.slideshow_mode:
  4103. self.toggle_slideshow(None)
  4104. if self.verbose and self.currimg_name != "":
  4105. print _("Yükleniyor: %s") % self.currimg_name
  4106. try:
  4107. self.load_new_image2(False, False, True, True)
  4108. # Calling load_new_image2 will reset the following two vars
  4109. # to 0, so ensure they are -1 again (no images preloaded)
  4110. self.preloadimg_prev_in_list = -1
  4111. self.preloadimg_next_in_list = -1
  4112. if not self.currimg_is_animation:
  4113. self.previmg_width = self.currimg_pixbuf.get_width()
  4114. else:
  4115. self.previmg_width = self.currimg_pixbuf.get_static_image().get_width()
  4116. self.image_loaded = True
  4117. first_image_loaded_successfully = True
  4118. if not self.closing_app:
  4119. while gtk.events_pending():
  4120. gtk.main_iteration(True)
  4121. except:
  4122. pass
  4123. if first_image_came_from_dir:
  4124. self.image_list = []
  4125. # Pre-load second image:
  4126. if second_image_found and not second_image_preloaded and ((not second_image_came_from_dir and self.curr_img_in_list+1 <= len(self.image_list)-1) or second_image_came_from_dir):
  4127. second_image_preloaded = True
  4128. temp = self.image_list
  4129. self.image_list = []
  4130. while len(self.image_list) < self.curr_img_in_list+1:
  4131. self.image_list.append(first_image)
  4132. self.image_list.append(second_image)
  4133. self.preload_next_image(False)
  4134. self.image_list = temp
  4135. if first_image_found:
  4136. # Sort the filelist and folderlist alphabetically, and recurse into folderlist:
  4137. if first_image_came_from_dir:
  4138. self.add_folderlist_images(folderlist, go_buttons_enabled)
  4139. self.do_image_list_stuff(first_image, second_image)
  4140. else:
  4141. self.do_image_list_stuff(first_image, second_image)
  4142. self.add_folderlist_images(folderlist, go_buttons_enabled)
  4143. self.update_title()
  4144. if not self.closing_app:
  4145. while gtk.events_pending():
  4146. gtk.main_iteration(True)
  4147. if not first_image_loaded_successfully:
  4148. self.image_load_failed(False, init_image)
  4149. self.searching_for_images = False
  4150. self.update_statusbar()
  4151. self.set_go_navigation_sensitivities(False)
  4152. self.set_slideshow_sensitivities()
  4153. self.thumbpane_update_images(True, self.curr_img_in_list)
  4154. if not self.closing_app:
  4155. self.change_cursor(None)
  4156. self.recursive = False
  4157. def add_folderlist_images(self, folderlist, go_buttons_enabled):
  4158. if len(folderlist) > 0:
  4159. folderlist.sort(locale.strcoll)
  4160. folderlist = list(set(folderlist))
  4161. for item in folderlist:
  4162. if not self.closing_app:
  4163. if (not self.open_hidden_files and os.path.basename(item)[0] != '.') or self.open_hidden_files:
  4164. self.stop_now = False
  4165. self.expand_directory(item, False, go_buttons_enabled, True, True)
  4166. def do_image_list_stuff(self, first_image, second_image):
  4167. if len(self.image_list) > 0:
  4168. self.set_go_navigation_sensitivities(True)
  4169. self.image_list = list(set(self.image_list))
  4170. self.image_list.sort(locale.strcoll)
  4171. def expand_directory(self, item, stop_when_second_image_found, go_buttons_enabled, update_window_title, print_found_msg):
  4172. if not self.stop_now and not self.closing_app:
  4173. folderlist = []
  4174. filelist = []
  4175. if not os.access(item, os.R_OK):
  4176. return False
  4177. for item2 in os.listdir(item):
  4178. if not self.closing_app and not self.stop_now:
  4179. while gtk.events_pending():
  4180. gtk.main_iteration(True)
  4181. item2 = item + os.sep + item2
  4182. item_fullpath2 = os.path.abspath(item2)
  4183. if (not self.open_hidden_files and os.path.basename(item_fullpath2)[0] != '.') or self.open_hidden_files:
  4184. if os.path.isfile(item_fullpath2) and self.valid_image(item_fullpath2):
  4185. filelist.append(item2)
  4186. if self.verbose and print_found_msg:
  4187. self.images_found += 1
  4188. print _("Found: %(fullpath)s [%(number)i]") % {'fullpath': item_fullpath2, 'number': self.images_found}
  4189. elif os.path.isdir(item_fullpath2) and self.recursive:
  4190. folderlist.append(item_fullpath2)
  4191. elif self.verbose:
  4192. print _("Skipping: %s") % item_fullpath2
  4193. if len(self.image_list)>0 and update_window_title:
  4194. self.update_title()
  4195. # Sort the filelist and folderlist alphabetically:
  4196. if len(filelist) > 0:
  4197. filelist.sort(locale.strcoll)
  4198. for item2 in filelist:
  4199. if not item2 in self.image_list:
  4200. self.image_list.append(item2)
  4201. if stop_when_second_image_found and len(self.image_list)==2:
  4202. return
  4203. if not go_buttons_enabled and len(self.image_list) > 1:
  4204. self.set_go_navigation_sensitivities(True)
  4205. go_buttons_enabled = True
  4206. # Recurse into the folderlist:
  4207. if len(folderlist) > 0:
  4208. folderlist.sort(locale.strcoll)
  4209. for item2 in folderlist:
  4210. if not self.stop_now:
  4211. self.expand_directory(item2, stop_when_second_image_found, go_buttons_enabled, update_window_title, print_found_msg)
  4212. def register_file_with_recent_docs(self, imgfile):
  4213. self.recent_file_add_and_refresh(imgfile)
  4214. if os.path.isfile(imgfile) and gtk.check_version(2, 10, 0) == None:
  4215. try:
  4216. gtk_recent_manager = gtk.recent_manager_get_default()
  4217. uri = ''
  4218. if imgfile[:7] != 'file://':
  4219. uri = 'file://'
  4220. uri = uri + urllib.pathname2url(os.path.abspath(imgfile))
  4221. gtk_recent_manager.add_item(uri)
  4222. except:
  4223. #Isnt currently functional on win32
  4224. if sys.platform == "win32":
  4225. pass
  4226. else:
  4227. raise
  4228. def valid_image(self, file):
  4229. test = gtk.gdk.pixbuf_get_file_info(file)
  4230. if test == None:
  4231. return False
  4232. elif test[0]['name'] == "wbmp":
  4233. # some regular files are thought to be wbmp for whatever reason,
  4234. # so let's check further.. :(
  4235. try:
  4236. test2 = gtk.gdk.pixbuf_new_from_file(file)
  4237. return True
  4238. except:
  4239. return False
  4240. else:
  4241. return True
  4242. def image_flip(self, old_pix, vertical):
  4243. width = old_pix.get_width()
  4244. height = old_pix.get_height()
  4245. d = None
  4246. if vertical:
  4247. d, w, h, rws = imgfuncs.vert(old_pix.get_pixels(), width, height, old_pix.get_rowstride(), old_pix.get_n_channels())
  4248. else:
  4249. d, w, h, rws = imgfuncs.horiz(old_pix.get_pixels(), width, height, old_pix.get_rowstride(), old_pix.get_n_channels())
  4250. if d:
  4251. new_pix = gtk.gdk.pixbuf_new_from_data(d, old_pix.get_colorspace(), old_pix.get_has_alpha(), old_pix.get_bits_per_sample(), w, h, rws)
  4252. return new_pix
  4253. return old_pix
  4254. def image_rotate(self, old_pix, full_angle):
  4255. width = old_pix.get_width()
  4256. height = old_pix.get_height()
  4257. angle = full_angle - (int(full_angle) / 360) * 360
  4258. if angle:
  4259. d = None
  4260. if angle % 270 == 0:
  4261. d, w, h, rws = imgfuncs.right(old_pix.get_pixels(), width, height, old_pix.get_rowstride(), old_pix.get_n_channels())
  4262. elif angle % 180 == 0:
  4263. d, w, h, rws = imgfuncs.mirror(old_pix.get_pixels(), width, height, old_pix.get_rowstride(), old_pix.get_n_channels())
  4264. elif angle % 90 == 0:
  4265. d, w, h, rws = imgfuncs.left(old_pix.get_pixels(), width, height, old_pix.get_rowstride(), old_pix.get_n_channels())
  4266. if d:
  4267. new_pix = gtk.gdk.pixbuf_new_from_data(d, old_pix.get_colorspace(), old_pix.get_has_alpha(), old_pix.get_bits_per_sample(), w, h, rws)
  4268. return new_pix
  4269. return old_pix
  4270. def toggle_slideshow(self, action):
  4271. if len(self.image_list) > 1:
  4272. if not self.slideshow_mode:
  4273. if self.slideshow_in_fullscreen and not self.fullscreen_mode:
  4274. self.enter_fullscreen(None)
  4275. self.slideshow_mode = True
  4276. self.update_title()
  4277. self.set_slideshow_sensitivities()
  4278. if not self.curr_slideshow_random:
  4279. self.timer_delay = gobject.timeout_add(int(self.curr_slideshow_delay*1000), self.goto_next_image, "ss")
  4280. else:
  4281. self.reinitialize_randomlist()
  4282. self.timer_delay = gobject.timeout_add(int(self.curr_slideshow_delay*1000), self.goto_random_image, "ss")
  4283. self.ss_start.hide()
  4284. self.ss_stop.show()
  4285. timer_screensaver = gobject.timeout_add(1000, self.disable_screensaver_in_slideshow_mode)
  4286. else:
  4287. self.slideshow_mode = False
  4288. gobject.source_remove(self.timer_delay)
  4289. self.update_title()
  4290. self.set_slideshow_sensitivities()
  4291. self.set_zoom_sensitivities()
  4292. self.ss_stop.hide()
  4293. self.ss_start.show()
  4294. def update_title(self):
  4295. if len(self.image_list) == 0:
  4296. title = "Mirage"
  4297. else:
  4298. title = "Mirage - " +_("[%(current)i of %(total)i]") % {'current': self.curr_img_in_list+1, 'total': len(self.image_list)} + ' ' + os.path.basename(self.currimg_name)
  4299. if self.slideshow_mode:
  4300. title = title + ' - ' + _('Slayt Gösterisi Modu')
  4301. self.window.set_title(title)
  4302. def slideshow_controls_show(self):
  4303. if not self.slideshow_controls_visible and not self.controls_moving:
  4304. self.slideshow_controls_visible = True
  4305. self.ss_delayspin.set_value(self.curr_slideshow_delay)
  4306. self.ss_randomize.set_active(self.curr_slideshow_random)
  4307. if self.slideshow_mode:
  4308. self.ss_start.set_no_show_all(True)
  4309. self.ss_stop.set_no_show_all(False)
  4310. else:
  4311. self.ss_start.set_no_show_all(False)
  4312. self.ss_stop.set_no_show_all(True)
  4313. (xpos, ypos) = self.window.get_position()
  4314. screen = self.window.get_screen()
  4315. self.slideshow_window.set_screen(screen)
  4316. self.slideshow_window2.set_screen(screen)
  4317. self.slideshow_window.show_all()
  4318. self.slideshow_window2.show_all()
  4319. if not self.closing_app:
  4320. while gtk.events_pending():
  4321. gtk.main_iteration()
  4322. ss_winheight = self.slideshow_window.allocation.height
  4323. ss_win2width = self.slideshow_window2.allocation.width
  4324. winheight = self.window.allocation.height
  4325. winwidth = self.window.allocation.width
  4326. y = -3.0
  4327. self.controls_moving = True
  4328. while y < ss_winheight:
  4329. self.slideshow_window.move(2+xpos, int(winheight-y-2))
  4330. self.slideshow_window2.move(winwidth-ss_win2width-2+xpos, int(winheight-y-2))
  4331. y += 0.05
  4332. if not self.closing_app:
  4333. while gtk.events_pending():
  4334. gtk.main_iteration()
  4335. self.controls_moving = False
  4336. def slideshow_controls_hide(self):
  4337. if self.slideshow_controls_visible and not self.controls_moving:
  4338. self.slideshow_controls_visible = False
  4339. (xpos, ypos) = self.window.get_position()
  4340. ss_winheight = self.slideshow_window.allocation.height
  4341. ss_win2width = self.slideshow_window2.allocation.width
  4342. winheight = self.window.allocation.height
  4343. winwidth = self.window.allocation.width
  4344. y = float(self.slideshow_window.allocation.height*1.0)
  4345. self.controls_moving = True
  4346. while y > -3:
  4347. self.slideshow_window.move(2+xpos, int(winheight-y-2))
  4348. self.slideshow_window2.move(winwidth-ss_win2width-2+xpos, int(winheight-y-2))
  4349. y -= 0.05
  4350. if not self.closing_app:
  4351. while gtk.events_pending():
  4352. gtk.main_iteration()
  4353. self.controls_moving = False
  4354. def disable_screensaver_in_slideshow_mode(self):
  4355. if self.slideshow_mode and self.disable_screensaver:
  4356. test = os.spawnlp(os.P_WAIT, "/usr/bin/xscreensaver-command", "xscreensaver-command", "-deactivate")
  4357. if test <> 127:
  4358. timer_screensaver = gobject.timeout_add(1000, self.disable_screensaver_in_slideshow_mode)
  4359. def main(self):
  4360. gtk.main()
  4361. if __name__ == "__main__":
  4362. base = Base()
  4363. gtk.gdk.threads_enter()
  4364. base.main()
  4365. gtk.gdk.threads_leave()